SunView"! System Programmer’s Guide
. \\
OvW
/x N y/.
'// K
/A vX/
x\v
Part Number: 800-1784-10
Revision A, of 9 May 1988
Sun Workstation and the Sun logo
are trademarks of Sun Microsystems, Incorporated.
SunView is a trademark of Sun Microsystems, Incorporated.
UNIX® is a registered trademark of AT&T.
All other products or services mentioned in this document are
identified by the trademarks or service marks of their
respective companies or organizations.
Copyright © 1982, 1983, 1984, 1985, 1986, 1987, 1988 by Sun Microsystems, Inc.
This publication is protected by Federal Copyright Law, with all rights reserved. No part of this publication may be
reproduced, stored in a retrieval system, translated, transcribed, or transmitted, in any form, or by any means manual,
electric, electronic, electro-magnetic, mechanical, chemical, optical, or otherwise, without prior explicit written per¬
mission from Sun Microsystems.
Contents
Chapter 1 Introduction ..... 3
What is SunView?. 3
Changes From Release 2.0. 3
Organization of Documentation. 3
Compatibility. 3
Changes in Release 4.0. 4
Chapter 2 Overview. 7
2.1. SunView Architecture. 7
2.2. Document Outline. 7
Chapter 3 SunView System Model. 11
3.1. A Hierarchy of Abstractions. 11
Data Managers. 13
Data Representations. 13
3.2. Model Dynamics. 13
Tiles and the Agent.......... 14
Windows....... 14
Desktop. 15
Locking....... ; . 1 6
Colormap Sharing. 16
Workstations. V? :: " .17
Chapter 4 The Agent & Tiles
21
Contents — Continued
4.1. Registering a Tile With the Agent. 21
Laying Out Tiles . 22
Dynamically Changing Tile Flags. 23
Extracting Tile Data... 23
4.2. Notifications From the Agent. 23
4.3. Posting Notifications Through the Agent. 24
4.4. Removing a Tile From the Agent. 26
Chapter 5 Windows. 29
5.1. Window Creation, Destruction, and Reference. 29
A New Window. 29
An Existing Window. 30
References to Windows. 30
5.2. Window Geometry. 31
Querying Dimensions... 31
The Saved Rect. 32
5.3. The Window Hierarchy. 32
Setting Window Links. 32
Activating the Window. 33
Defaults. 33
Modifying Window Relationships. 34
Window Enumeration. 35
Enumerating Window Offspring. 35
Fast Enumeration of the Window Tree. 36
5.4. Pixwin Creation and Destruction. 36
Creation. 36
Region. 37
Retained Image. 37
Bell . 37
Destruction. 37
5.5. Choosing Input. 37
Input Mask. 37
Manipulating the Mask Contents. 38
Contents — Continued
Setting a Mask. 38
Querying a Mask. 39
The Designee. 39
5.6. Reading Input. 39
Non-blocking Input. 39
Asynchronous Input. 39
Events Pending. 40
5.7. User Data. 40
5.8. Mouse Position. 40
5.9. Providing for Naive Programs . 41
Which Window to Use. 41
The Blanket Window. 41
5.10. Window Ownership. 42
5.11. Environment Parameters. 42
5.12. Error Handling. 43
Chapter 6 Desktops. 47
Look at sunview. 47
6.1. Multiple Screens. 47
The singlecolor Structure. 47
The screen Structure. 48
Screen Creation. 48
Initializing the screen Structure . 49
Screen Query. 49
Screen Destruction. 49
Screen Position. 49
Accessing the Root FD. 50
Chapter 7 Workstations. 53
7.1. Virtual User Input Device. 53
What Kind of Devices?. 53
Vuid Features. 54
Vuid Station Codes... 54
Contents — Continued
Address Space Layout. 54
Adding a New Segment. 55
Input State Access. 55
Unencoded Input. 55
7.2. User Input Device Control. 56
Distinguished Devices. 56
Arbitrary Devices. 57
Non-Vuid Devices. 57
Device Removal. 57
Device Query. 57
Device Enumeration. 58
7.3. Focus Control. 58
Keyboard Focus Control. 58
Event Specification. 59
Setting the Caret Event. 59
Getting the Caret Event. 59
Restoring the Caret. 59
7.4. Synchronization Control. 60
Releasing the Current Event Lock. 60
Current Event Lock Breaking. 60
Getting/Setting the Event Lock Timeout. 61
7.5. Kernel Tuning Options. 61
Changing the User Actions that Affect Input. 63
Chapter 8 Advanced Notifier Usage. 67
8 . 1 . Overview. 67
Contents. 67
Viewpoint. 67
Further Information. 67
8.2. Notification. 68
Client Events. 68
Delivery Times. 68
Handler Registration. 68
Contents — Continued
The Event Handler. 69
SunView Usage. 69
Output Completed Events. 69
Exception Occurred Events. 70
Getting an Event Handler. 70
8.3. Interposition. 72
Registering an Interposer. 72
Invoking the Next Function. 73
Removing an Interposed Function. 74
8.4. Posting. 77
Client Events. 77
Delivery Time Hint. 77
Actual Delivery Time. 77
Posting with an Argument. 78
Storage Management. 78
SunView Usage. 79
Posting Destroy Events. 80
Delivery Time. 80
Immediate Delivery. 80
Safe Delivery. 80
8.5. Prioritization. 81
The Default Prioritizer. 81
Providing a Prioritizer. 81
Dispatching Events. 82
Getting the Prioritizer. 83
8.6. Notifier Control. 85
Starting. 85
Stopping. 85
Mass Destruction. 85
Scheduling. 86
Dispatching Clients. 86
Getting the Scheduler. 87
Client Removal. 87
- vii-
Contents — Continued
8.7. Error Codes. 88
8 . 8 . Restrictions on Asynchronous Calls into the Notifier. 90
8.9. Issues. 91
Chapter 9 The Selection Service and Library. 95
9.1. Introduction. 95
9.2. Basic Concepts. 96
9.3. Fast Overview. 96
The Selection Service vs. the Selection Library. 97
9.4. Selection Service Protocol: an Example. 97
Secondary Selection Between Two Windows. 97
Notes on the Above Example. 101
9.5. Topics in Selection Processing. 101
Reporting Function-Key Transitions... 101
Sending Requests to Selection Holders. 102
Long Request Replies. 104
Acquiring and Releasing Selections. 104
Callback Procedures: Function-Key Notifications. 104
Responding to Selection Requests. 105
Callback Procedures: Replying to Requests. 106
9.6. Debugging and Administrative Facilities. 109
9.7. Other Suggestions. 109
If You Die. 109
9.8. Reference Section. 110
Required Header Files. 110
Enumerated Types. 110
Other Data Definitions. 110
Procedure Declarations. 112
9.9. Common Request Attributes. 121
9.10. Two Program Examples. 125
get selection Code. 125
seln_demo ... 128
Large Selections. 128
Contents — Continued
Chapter 10 The User Defaults Database. 145
Why a Centralized Database?. 145
10.1. Overview. 146
Master Database Files. 146
Private Database Files. 146
10.2. File Format. 147
Option Names. 147
Option Values. 148
Distinguished Names. 148
$Help. 148
$Enumeration. 148
$Message. 149
10.3. Creating a . d File: Example. 149
10.4. Retrieving Option Values. 150
Retrieving String Values. 150
Retrieving Integer Values. 150
Retrieving Character Values. 151
Retrieving Boolean Values. 151
Retrieving Enumerated Values. 152
Searching for Specific Symbols. 152
Searching for Specific Values. 153
Retrieving all Values in the Database. 153
10.5. Conversion Programs. 154
10.6. Property Sheets. 155
10.7. Error Handling. 156
Error_Action . 156
Maximum_Errors . 157
TestMode . 157
10.8. Interface Summary. 157
10.9. Example Program: filer Defaults Version. 160
Chapter 11 Advanced Imaging. 173
11.1. Handling Fixup. 173
Contents — Continued
11.2. Icons. 174
Loading Icons Dynamically. 174
Icon File Format. 174
11.3. Damage. 176
Handling a SIGWINCH Signal. 176
Image Fixup. 176
11.4. Pixwin Offset Control. 178
Chapter 12 Menus & Prompts. 181
12 . 1 . Full Screen Access. 181
Initializing Fullscreen Mode. 182
Releasing Fullscreen Mode. 182
Seizing All Inputs. 182
Grabbing I/O. 182
Releasing I/O. 182
12.2. Surface Preparation. 182
Multiple Plane Groups. 183
Pixel Caching. 183
Saving Screen Pixels. 1 83
Restoring Screen Pixels. 1 84
Fullscreen Drawing Operations. 184
Chapter 13 Window Management. 189
Tool Invocation. 190
Utilities. 190
13.1. Minimal Repaint Support. 192
Chapter 14 Rects and Rectlists. 197
14.1. Rects. 197
Macros on Rects. 197
Procedures and External Data for Rects. 198
14.2. Rectlists. 199
Macros and Constants Defined on Rectlists. 200
Contents — Continued
Procedures and External Data for Rectlists . 200
Chapter 15 Scrollbars. 205
15.1. Basic Scrollbar Management. 205
Registering as a Scrollbar Client. 205
Keeping the Scrollbar Informed. 206
Handling the SCROLL_REQUEST Event. 207
Performing the Scroll. 208
Normalizing the Scroll. 209
Painting Scrollbars. 209
15.2. Advanced Use of Scrollbars. 209
Types of Scrolling Motion in Simple Mode. 210
Types of Scrolling Motion in Advanced Mode. 211
Appendix A Writing a Virtual User Input Device Driver. 215
A.l. Firm Events. 215
The Firm_event Structure. 215
Pairs. 216
Choosing VUID Events. 217
A.2. Device Controls. 217
Output Mode. 217
Device Instancing. 217
Input Controls. 218
A. 3. Example. 218
Appendix B Programming Notes.. 229
B. l. What Is Supported?. 229
B.2. Library Loading Order. 229
B.3. Shared Libraries vs. Shared Text. 229
Shared Libraries. _ 229
B.4. Error Message Decoding. 230
B.5. Debugging Hints. 230
Disabling Locking . 230
-XI-
Contents — Continued
B.6. Sufficient User Memory. 231
B.7. Coexisting with UNIX. 232
Tool Initialization and Process Groups. 232
Signals from the Control Terminal. 232
Job Control and the C Shell. 232
Index. 235
— xii —
Tables
Table 9-1 Selection Service Scenario. 98
Table 10-1 Defaults Metacharacters. 148
Table 10-2 Default Procedures. 157
Table 14-1 Rectlist Predicates. 201
Table 14-2 Rectlist Procedures. 202
Table 15-1 Scroll-Related Scrollbar Attributes. 210
Table 15-2 Scrollbar Motions. 212
Table B-l Variables for Disabling Locking. 231
— xiii —
Figures
Figure 3-1 SunView System Hierarchy
12
v.v.v.%v.\v.v.v.v.v.v»v.%v*v.\v.v*%v.v.v.v.v.\
Introduction
Introduction. 3
What is SunView?. 3
Changes From Release 2.0. 3
Organization of Documentation. 3
Compatibility. 3
Changes in Release 4.0 . 4
Introduction
What is SunView?
SunView is a system to support interactive, graphics-based applications running
within windows. It consists of two major levels of functionality: the application
level and the system level. The system level is described in this document and
covers two major areas: the building blocks on which the application level is
built and advanced application-related features.
Changes From Release 2.0
SunView is an extension and refinement of SunWindows 2.0, containing many
enhancements, bug fixes and new facilities not present in SunWindows. How¬
ever, the changes preserve source level compatibility between SunWindows 2.0
and SunView.
Organization of
Documentation
These changes are reflected in the current organization of the SunView documen¬
tation. The material on Pixrects from the old SunWindows Reference Manual is
in a new document titled Pixrect Reference Manual, uch of the functionality of
The 2.0 SunWindows Reference
Manual has not been reprinted for
SunView.
the SunWindows window and tool layers has been incorporated into the new
SunView interface. The basic SunView interface, intended to meet the needs of
simple and moderately complex applications, is documented in the application-
level manual, the SunView 1 Programmer’s Guide.
This document is the SunView 1 System Programmer’s Guide. It contains a com¬
bination of new and old material. Several of its chapters document new facilities
such as the Notifier, the Agent, the Selection Service and the defaults package.
Also included is low-level material from the old SunWindows Reference Manual
— e.g. the window manager routines — of interest to implementors of window
managers and other advanced applications.
This document is an extension of the application-level manual. You should only
delve into this manual if the information in the SunView 1 Programmer's Guide
manual doesn’t answer your needs. Thus, you should read the application-level
manual first.
Compatibility
Another consideration is compatibility with future releases. Most of the objects
in the SunView 1 Programmer’s Guide are manipulated through an opaque attri¬
bute value interface. Code that uses them will be more portable to future ver¬
sions of SunView than if it uses the routines documented in this manual which
assume particular data structures and explicit parameters. If you do use these
routines then the code should be encapsulated so that low-level details are
V microsystems
3
Revision A, of May 9, 1988
4 Sun View 1 System Programmer’s Guide
Keep your old documentation
Changes in Release 4.0
isolated from the rest of your application.
On the way to SunView, we have discarded documentation about the internals of
some data structures that were discussed in SunWindows 2.0. In addition, we
have discarded documentation about routines whose functionality is now pro¬
vided by the interface discussed in the SunView 1 Programmer’s Guide. Thus, if
your application is based on the SunWindows programming interface, you should
keep your 2.0 documentation. In particular, the following structures are no
longer documented (there may by others): tool, pixwin, toolsw, and
toolio.
SunOS Release 4.0 includes further enhancements to the higher-level SunView
programmatic interface documented in the SunView 1 Programmer’s Guide, such
as alerts, shadowed subframes, ‘Props’ actions, and so on . Sun encourages pro¬
grammers to use these higher-level interfaces in preference to low-level routines
documented in this manual whenever possible; this will help to insulate your
applications from changes in the low-level window-system interfaces underneath
SunView.
microsystems
Revision A, of May 9, 1988
v!\v ::'v
*w. , .wKwKvWv»w
.w'AVWv.mwXwKv
Overview
Overview. 7
2.1. SunView Architecture. 7
2.2. Document Outline. 7
Overview
2.1. Sun View Architecture From a system point of view, SunView is a two-tiered system, consisting of the
application and system layers:
□ The application layer provides a set of high-level objects, including windows
of different types, menus, scrollbars, buttons, sliders, etc., which the client
can assemble into an application, or tool. This layer is sometimes referred to
as the tool layer. The functionality provided at this level should suffice for
most applications. This layer is discussed in the SunView 1 Programmer’s
Guide.
□ At the system layer a window is presented not as an opaque object but in
terms which are familiar to UNIX programmers — as a device which the
client manipulates through a file descriptor returned by an open (2) call.
This layer is sometimes referred to as the window device layer. The manipu¬
lation and multiplexing of multiple window devices is the subject of much
of this document. The term “window device” is often shortened to just
window in this document.
2.2. Document Outline This document covers the follow system level topics:
□ A system model which presents the levels, components and inter¬
relationships of the window system.
□ A SunView mechanism, called the Agent, which includes:
• notification of window damage and size changes.
• reading and distribution of input events among windows within a pro¬
cess.
• posting events with the Agent for delivery to other clients,
p Windows as devices, which includes:
• reading control options such as asynchronous input and non-blocking
input.
o The screen abstraction, called a desktop, which includes:
• Routines to initialize new screens so that SunView may be run on them.
• Multiple screens accessible by a single user.
®sun
\r microsystems
7
Revision A, of May 9,1988
8 SunView 1 System Programmer’s Guide
□ The global input abstraction, called a workstation, which includes:
• environment wide input device instantiation.
• controlling a variety of system performance and user interface options.
• extending the Virtual User Input Device interface with events of your
own design.
□ Advanced use of the general notification-based flow of control management
mechanism called the Notifier, which includes:
• detection of input pending, output completed and exception occurred on
a file descriptor.
• maintenance of interval timers.
• dispatching of signal notifications.
• child process status and control facilities.
• a client event notification mechanism, which can be thought of as a
client-defined signal mechanism.
□ The Selection Service, for exchanging objects and information between
cooperative client, both within and between processes.
□ The defaults mechanism, for maintaining and querying a database of user-
settable options.
□ Advanced imaging topics, which include:
• the repair of damaged portions of your window, when not retained.
• receiving window damage and size change notifications via
SIGWINCH.
□ The mechanisms used to violate window boundaries. You would use them if
you created a menu or prompt package.
o Routines to perform window management activities such as open, close,
move, stretch, top, bottom, refresh. In addition, there are facilities for invok¬
ing new tools and positioning them on the screen.
□ Routines to manipulate individual rectangles and lists of rectangular areas.
They forms what is essentially an algebra of rectangles, useful in computing
window overlap, points in windows, etc.
□ Advanced icon topics, including displaying them, accessing them from a
file, their internal structure, etc..
□ Advanced scrollbar topics, including calculating and performing your own
scroll motions (in a canvas, for example).
Finally, there is an appendix on how to write a line discipline for a new input
device that you want to access through SunView. Another appendix covers some
programming notes.
Revision A, of May 9, 1988
tV.WiV.V.V.WKV.W*V.V.V.V*V.VtV.V.V.V*W>.V.W
SunView System Model
SunView System Model. 11
3.1. A Hierarchy of Abstractions. 11
Data Managers. 13
Data Representations. 13
3.2. Model Dynamics. 13
Tiles and the Agent. 14
Windows. 14
Desktop. 15
Locking. 16
Colormap Sharing. 16
Workstations. 17
■
#
3
SunView System Model
3.1. A Hierarchy of
Abstractions
This chapter presents the system model of SunView. It discusses the hierarchy of
abstractions that make up the window system, the data representations of those
abstractions and the packages that manage the components.
There is a hierarchy of abstractions that make up the window system:
• Tiles are used to tile the surface of a window. Tiles don’t overlap and may
not be nested. For example, a text subwindow with a scrollbar is imple¬
mented with separate tiles for both the scrollbar and the text portion of the
subwindow.
• Windows are allowed to overlap one another 1 and may be arbitrarily nested.
Frames, panels, text subwindows, canvases and the root window are all
implemented as windows.
• Screens, sometimes called desktops, support multiple windows and represent
physical display devices. A screen is covered by the root window.
• Workstations support multiple screens that share common user input devices
on the behalf a single user. For example, one can slide the cursor between
screens.
The figure below shows the hierarchy:
' The procedure which lays out subwindows of tools does it so they do not overlap, but this is not an
inherent restriction.
#sun
\r microsystems
11
Revision A, of May 9, 1988
12 Sun View 1 System Programmer’s Guide
Figure 3-1 SunView System Hierarchy
®sun
\r microsystems
Revision A, of May 9, 1988
Chapter 3 — Sun View System Model 13
Data Managers
Data Representations
3.2. Model Dynamics
The various parts of the system support the management of this hierarchy. They
provide the glue between the various components:
• The window driver, (currently) residing in the UNIX kernel as a pseudo dev¬
ice driver that is accessed through library routines, supports windows,
screens and workstations.
• The pixwin library package allows implementors of specific windows and
tiles to access the screen for drawing.
• The Notifier library package is used to support the general flow of control to
multiple disjoint clients.
• The Agent library package can be viewed as the SunView-specific extension
of the Notifier. The Agent supports tiles and windows.
• The Selection Service is a separate user process that supports the inter¬
process communication and control of user selection related data. In this
role it essentially supports specific tile implementations.
This conceptual model is useful to understand the structure and workings of the
system. However, the model doesn’t always translate into corresponding objects:
• Tiles are implemented as opaque handles with pixwin regions used to com¬
municate the size and position of the tile to the Agent.
• At the system level, windows are implemented as UNIX devices which are
represented by file descriptors. Window devices are not to be confused with
the application level notion of windows which are opaque handles. A file
descriptor is returned by open(2) of an entry in the /dev directory. It is
manipulated by other system calls, such as select(2), read(2),
ioctl(2), and close(2).
• There is a screen structure that describes a limited number of properties of a
desktop. However, it is a window file descriptor that is used as the “ticket”
into the window driver to get and set screen related data. This is possible
because a window is directly associated with a particular screen.
• There is no system object that translates into a workstation. However, like
desktop data, workstation-related data is accessed using a window file
descriptor. Again, this is because a window is directly associated with a par¬
ticular screen which is directly associated with a particular workstation. As
a side effect of this association, one can use the file descriptor of a panel and
asked about workstation related data for the workstation on which the panel
resides.
Now that you have been introduced to the players in the window system, let’s see
how they interact.
microsystems
Revision A, of May 9, 1988
14 Sun View 1 System Programmer’s Guide
Tiles and the Agent
Windows
Tiles are quite simple and “lightweight” abstractions. The main reason for hav¬
ing tiles instead of yet another nesting of windows is that file descriptors are rela¬
tively heavyweight. There can only be 64 file descriptors open per UNIX process
in Sun’s release 4.0. As a result, a tile provides only a subset of the functionality
of a full-blown window. After telling the Agent that a tile covers a certain por¬
tion of the window, the Agent provides the following services:
• The Agent tells you when your tile has been resized.
• The Agent tells you when your tile should be repainted. Optionally, you can
tell the Agent to maintain a retained image for your tile from which the
Agent can handle the repainting itself.
• The Agent reads input for the tile’s window and distributes it to the
appropriate tile.
• The Agent notices when tile regions have been entered and exited by the
cursor and notifies the tile.
In addition, the Agent is the conduit by which client generated events are passed
between tiles. For example, when the scrollbar wants to tell a canvas that it
should now scroll, the communications is arranged via the Agent. The Agent, in
turn, uses the Notifier to implement the data transfer.
It is your responsibility to lay out your window’s tiles so that they don’t overlap,
even when the window size changes.
Even a window with only a single tile that covers its entire surface may use the
Agent and its features.
Windows are the focus of most of the functionality of the window system. Here
is a list of the information about a window maintained by the window system:
• A rectangle refers to the size and position of a window. Some windows
(frames) also utilize an alternative rectangle that describes the iconic posi¬
tion of a window.
• Each window has a series of links that describe the window’s position in a
hierarchical database, which determines its overlapping relationships to
other windows. Windows may be arbitrarily nested, providing distinct
subwindows within an application’s screen space.
• Arbitration between windows is provided in the allocation of display space.
Where one window limits the space available to another, clipping, guaran¬
tees that one does not interfere with the other’s image. One such conflict
arises when windows share the same coordinates on the display: one over¬
laps the other. Thus, clipping information is associated with each window.
• When one window impacts another window’s image without any action on
the second window’s part, the window system informs the affected window
of the damage it has suffered, and the areas that ought to be repaired. To do
this the window system maintains a description of the portion of the window
of the display that is corrupted as well as the process id of the window’s
owner.
microsystems
Revision A, of May 9, 1988
Chapter 3 — Sun View System Model 15
• On color displays, colormap entries are a scarce resource. When shared
among multiple applications, they become even more scarce: there may be
simultaneous demand for more colors than the display can support. Arbitra¬
tion between windows is provided in the allocation of colormap entries.
Provisions are made to share portions of the colormap (colormap segments).
There is colormap information that describes that portion of the colormap
assigned to a window.
• Real-time response is important when tracking the cursor, so this is done by
the window system. Thus, the image (cursor and optional cross hairs) used
to track the mouse when it is in the window is part of the window’s data. 2
• Windows may be selective about which input events they will process, and
rejected events will be offered to other windows for processing; you can
explicitly designate the window rejected events are first offered to. 3 A mask
indicates what keyboard input actions the window should be notified of and
there is a similar mask for pick/locator-related actions.
• A window device is read in order to receive the user input events directed at
it. So like other input devices a window supports a variety of the input
modes, such as blocking or non-blocking, synchronous or asynchronous, etc.
In addition, there is a queue of input events that are pending for a window.
• There are 32 bits of data private to the window client stored with the win¬
dow.
Desktop
Desktop data relates to the physical display:
• The physical display is associated with a UNIX device. The desktop main¬
tains the name of this device.
• The desktop maintains the notion of a default foreground and background
color.
• The desktop records the size of the screen.
• The desktop maintains the name of the distinguished root window on itself.
• When multiple screens are part of a workstation, each desktop knows the
relative physical placement of its neighboring displays so that the mouse
cursor may slide between them.
2 There is only one cursor per window, but the image may be different in different tiles within the window
(e.g. scrollbars have different cursors). If so, the different cursor images are dynamically loaded by the user
process and thus real time response is not assured.
3 Not all events are passed on to a designee, for example window-specific events such as LOC WINENTER
and KBD_REQUEST are not.
Revision A, of May 9, 1988
16 Sun View 1 System Programmer’s Guide
Locking
Display Locking
Window Database Locking
Colormap Sharing
The desktop also arbitrates screen surface access and window database manipula¬
tion.
Display locking prevents window processes from interfering with each other in
several ways:
• Raster hardware may require several operations to complete a change to the
display; one process’ use of the hardware is protected from interference by
others during this critical interval.
• Changes to the arrangement of windows must be prevented while a process
is painting, lest an area be removed from a window as it is being painted.
• A software cursor that the window process does not control (the kernel is
usually responsible for the cursor) may have to be removed so that it does
not interfere with the window’s image.
Window database locking is used when doing multiple changes to the window’s
size, position, or links in the window hierarchy. This prevents any other process
from performing a conflicting modification and allows the window system to
treat changes as atomic.
On color displays, colormap entries are a limited resource. When shared among
multiple applications, colormap usage requires arbitration. Consider the follow¬
ing applications running on the same display at the same time in different win¬
dows:
• Application program X needs 64 colors for rendering VLSI images.
• Application program Y needs 32 shades of gray for rendering black and white
photographs.
• Application program Z needs 256 colors (assume this is the entire colormap)
for rendering full color photographs.
Colormap usage control is handled as follows:
• To determine how X and Y figure out what portion of the colormap they
should use (so they don’t access each others’ entries), the window system pro¬
vides a resource manager that allocates a colormap segment to each window
from the shared colormap. To reduce duplicate colormap segments, they are
named and can be shared among cooperating processes.
• To hide concerns about the correct offset to the start of a colormap segment
from routines that access the image, the window system initializes the image
of a window with the colormap segment offset. This effectively hides the
offset from the application.
• To accommodate Z if its large colormap segment request cannot be granted,
Z’s colormap is loaded into the hardware, replacing the shared colormap,
whenever the cursor is over Z’s window. Z’s request is not denied even
though it is not allocated its own segment in the shared colormap.
microsystems
Revision A, of May 9, 1988
Chapter 3 — SunView System Model 17
Workstations
The domain of a workstation is to manage the global state of input processing.
User inputs are unified into a single stream within the window system, so that
actions with the user input devices, usually a mouse and a keyboard, can be coor¬
dinated. This unified stream is then distributed to different windows, according
to user or programmatic indications. To this end a workstation manages the fol¬
lowing:
• A workstation needs some number of user input devices to run. A dis¬
tinguished keyboard device and a distinguished mouse-like device are recog¬
nized since these are required for a useful workstation. Non-Sun supported
user input devices may be used as these distinguished devices.
• Additional, non-distinguished user input devices, may be managed by a works¬
tation as well.
• The input devices associated with the workstation are polled by the window
system. Locator motion causes the cursor to move on the screen. Certain
interrupt event sequences are noted. Events are timestamped enqueued on the
workstation’s input queue based on the time they were generated.
• This input queue is massaged in a variety of ways. If the input queue becomes
full, locator motion events on the queue are compressed in order to reduce its
size. In addition, locator motion at the head of the queue is (conditionally)
collapsed so as to deliver the most up-to-date locator position to applications.
• Based on the state of input focuses and window input masks a window is
selected to receive the next event from the head of the input queue. The event
is placed on the window device’s separate input pending queue and the
window’s process is awoken.
• The workstation uses a synchronized input mechanism. The main benefit of a
synchronized input mechanism is that it removes the input race conditions
inherent in a multiple process environment. While a window processes the
input event the workstation waits for it to finish before handing out the next
event.
• The workstation deals with situations in which a process takes too long to
finish processing an input event by pressing on ahead in a partially synchron¬
ized mode until the errant process catches up to the user. This prevents a mis¬
behaving process from disabling user interaction with other processes.
microsystems
Revision A, of May 9, 1988
■
%
4
■K
The Agent & Tiles
The Agent & Tiles. 21
4.1. Registering a Tile With the Agent. 21
Laying Out Tiles . 22
Dynamically Changing Tile Flags. 23
Extracting Tile Data. 23
4.2. Notifications From the Agent. 23
4.3. Posting Notifications Through the Agent. 24
4.4. Removing a Tile From the Agent. 26
4
The Agent & Tiles
This chapter describes how to utilize the Agent to manage tiles for you. It con¬
tains the implementation details associated with tiles and the Agent, as intro¬
duced in the SunView System Model chapter. This chapter uses a text subwindow
with a scrollbar as an example of Agent utilization.^
4.1. Registering a Tile With The Agent is a little funny in that you don’t ask it to create a tile for you that it
the Agent will then manage. In fact tiles are only abstractions. Instead, you create a pixwin
region and a unique client object and pass these to the Agent to manage on your
behalf. The following routine is how this registration is done.
int
win_register(client, pw, event_func, destroy_func, flags)
Notify_client
client;
Pixwin
*pw;
Notify_func
event
func;
Notify_func
destroy__func;
u_ji.nt
flags;
#define PW_RETAIN
Oxl
#define PW_FIXED_IMAGE
0x2
♦define PW_INPUT DEFAULT
0x4
♦define PW_NO_LOC_
ADJUST
0x8
♦define PW REPAINT
ALL
0x10
client is the handle that the Agent will hand back to you when you are
notified of interesting events (see below) by a call to the event_f unc function,
client is usually the same client handle by which a tile is known to the
Notifier. Client handles needs to be unique among all the clients registered with
the Notifier.
pw is a pixwin opened by client and is the pixwin by which the tile writes to
the screen. This pixwin could have been created by a call to pw_open () if the
window has only a single tile that covers its entire surface. More often the tile
covers a region of the windows created by a call to pw_region (), documented
in the Clipping with Regions section of the Imaging Facilities: Pixwins chapter
4 The header file /usr/ include / sunwindow/window_hs .h contains the definitions for the routines
in this chapter.
V microsystems
21
Revision A, of May 9, 1988
22 SunView 1 System Programmer’s Guide
Laying Out Tiles
of the SunView 1 Programmer’s Guide. Regions are themselves pixwins that
refer to an area within an existing pixwin.
flags control the options utilized by the Agent when managing your tile:
□ PW_RETAIN — Your tile will be managed as retained. This means that the
window system maintains a backup image of your tile in memory from
which the screen can be refreshed in case the tile is exposed after being hid¬
den.
o PW_FIXED_IMAGE — The underlaying abstraction of the image that your
tile is displaying is fixed in size. This means that the client need not be
asked to repaint the entire tile on a window size change. Only the newly
exposed parts need be repainted.
□ PW_INPUT_DEFAULT — Usually, the cursor position over a tile indicates
which tile input will by sent to. However, if your window has the keyboard
focus, the cursor need not be over any tile in your window in order for the
window to be sent input. The tile with this flag on will receive input if the
cursor is not over any tile in the window. In our example, the text display
tile would be created with this flag on because it is the main tile in the win¬
dow.
□ PW_NO_LOC_AD JUST — Usually, when the Agent notifies your tile of an
event the locator x and y positions contained in your event are adjusted to be
relative to the tile’s upper left hand comer. Turning this flag on suppresses
this action which means that you’ll get events in the window’s coordinate
space.
□ PW_REPAINT_ALL — Setting this flag causes your tile to be completely
repainted when ever the Agent detects that any part of your window needs to
be repainted.
event_f unc is the client event notification function for the tile and
destroy_f unc is the client destroy function for the tile. The Agent actually
sets these functions up with the notifier (see the Notifier chapter in the SunView 1
Programmer’s Guide for a discussion of these two types of notification functions
and their calling conventions). In addition, the Agent gets input pending and
SIGWINCH received (used for repaint and resize detection) notifications from the
notifier and posts corresponding events to the appropriate tile. Tiles in the same
window need to share the same input pending notification procedure because
input is distributed from the kernel at a window granularity. Tiles also share the
same input masks, as well as other window data.
Tiles are used to tile the surface of a window. Tiles may not overlap and may not
be nested. As an example, a text subwindow with a scrollbar is implemented
with a separate tile for both the scrollbar and the text portion of the subwindow.
It is a window owner’s responsibility to layout tiles so that they don’t overlap.
The Agent does nothing for you in this regard, so layout is arranged via conven¬
tions among tiles. In our example, there are two tiles, the scrollbar and a text
display area. Here is how layout works when scrollbars are involved:
microsystems
Revision A, of May 9, 1988
Chapter 4 — The Agent & Tiles 23
Dynamically Changing Tile
Flags
□ The text subwindow code creates a vertical scrollbar. The scrollbar code
looks at the user’s scrollbar defaults and finds out what side to put the
scrollbar on and how wide it should be. Given this information it figures out
where to place its tile. The scrollbar code registers its new tile with the
Agent.
□ After creating the scrollbar, the text subwindow code asks the scrollbar what
side it is on and how thick it is. Given this information the text subwindow
figures out where to place its text display tile. The text subwindow code
registers its new tile with the Agent.
□ When a window resize notification (sent by the Agent) is received by the
scrollbar it knows to hug the side that it is on as it adjusts the size of its
region. A similar arrangement is followed by the text display tile.
The following routine lets you dynamically set the tile’s flags:
int
win_set_flags(client, flags)
Notify_client client;
u_int flags;
A —1 is returned if client is not registered, otherwise 0 is returned.
When you set a single flag, it is best to retrieve the state of all the flags first and
then operate on the bit that you are changing, then write all the flags back; other¬
wise, any other flags that are set will be reset. The following routine retrieves the
current flags of the tile associated with client:
u_int
win_get_flags(client)
Notify_client client;
Extracting Tile Data Extraction of interesting values from clients of the Agent is done via the follow¬
ing calls:
int
win_get_fd(client)
Notify_client client;
win_get_f d () gets the window file descriptor associated with client’s tile.
Pixwin *
win_get_pixwin(client)
Notify_client client;
win_get_pixwin () gets the pixwin associated with client’s tile.
Once you register your tile with the Agent, the Agent causes the event_f unc
you passed to win_register () to be called (“notified”) to handle events.
You must write your tile’s event notification procedure yourself; the events it
might receive are listed in the Handling Input chapter in the SunView 1
Programmer’s Guide.
4 . 2 . Notifications From the
Agent
microsystems
Revision A, of May 9, 1988
24 SunView 1 System Programmer’s Guide
The calling sequence for any client event notification function is:
Notify_value
event_func(client, event, arg, when)
Notify_client client;
Event *event;
Notify_arg arg;
Notify_event_type when;
client is the client handle passed into win_register (). event is the
event your tile is notified of. arg is usually NULL but depends on
event_id (event ). In the case of the scrollbar tile notifying the text display
tile of a scroll action arg is actually defined, when is described in the chapter
Advanced Notifier Usage and is usually NOTIFY_SAFE.
What your tile does with events is largely up to you; however, there are a few
things to note about certain classes of events.
□ For LOC_RGNENTER and LOC_RGNEXIT to be generated for tiles,
LOC_MOVE, LOC_WINENTER and LOC_WINEXIT need to be turned on.
Remember that tiles share their window’s input mask so they need to
cooperate in their use of it.
□ Locator coordinate translation is done so that the event is relative to a tile’s
coordinate system unless disabled by PW_NO_LOC_AD JUST.
□ On a WIN_RESIZE event, you can use pw_set_region_rect () to
change the size and position of your tile’s pixwin region.
□ On a WIN_REPAINT, you simply repaint your entire tile. The Agent will
have set the clipping of your pixwin so that only the minimum portion of the
screen will actually appear to repaint. Alternatively, if you have initially
told the Agent to maintain a retained image for your tile from which the
Agent can handle the repainting itself, you will only get a WIN_REPAINT
call after a window size change. You won’t even get this call if your tile’s
flags have PW_FIXED_IMAGE and PW_RETAIN bits turned on.
4.3. Posting Notifications
Through the Agent
The Agent follows the lead of the Notifier when it comes to posting events. See
the documentation on notif y_post_event () and
not if y_post_event_and_arg () in the Advanced Notifier Usage chapter
if you are going to be posting events between tiles.
There are four routines available for posting an event to another tile.
Notify_error
win_j?ost_id(client, id, when_hint)
Notify_client client;
short id;
Notify_event_type when_hint;
The Agent is the conduit by which client-generated events are passed between
tiles. For example, when the scrollbar wants to tell a canvas that it should now
scroll, the communications is arranged via the Agent. The Agent, in turn, uses
the Notifier to implement the data transfer.
IN u p
V microsystems
Revision A, of May 9, 1988
Chapter 4 — The Agent & Tiles 25
is provided if you want to send an event to a tile and you don’t really care about
any event data except the event__id (event). The Agent will generate the
remainder of the event for you with up-to-date data. when_hint is usually
NOTIFYJSAFE.
A second routine is available if you want to manufacture an event yourself. This
is easy if you already have an event in hand.
Notify_error
win_jpost_event (client, event, when_hint)
Notify_client client;
Event *event;
Notify_event_type when_hint;
The other two routines parallel the first two but include the capability to pass an
arbitrary additional argument to the destination tile. The calling sequence is
more complicated because one must make provisions to copy and later free the
additional argument in case the delivery of the event is delayed.
Notify__error
win_j?ost__id_and_arg (client, id, when_hint, arg,
copy_func, release_func)
Notify_client client;
short id;
Not if y__event_type when__hint ;
Notify__arg arg;
Notify_copy copy_func;
Notify_release release__func;
Notify_error
win__post_event_arg (client, event, when__hint, arg,
copy__func, release_func)
Notify_client client;
Event *event;
Notify_event_type when_hint;
Notify_arg arg;
Notify__copy copy_func;
Notify__release release_func;
The copy and release functions are covered in the Advanced Notifier Usage
chapter. After reading about them you will know why you need the following
utilities to copy the event as well as the arg:
Notify__arg
win_copy_event(client, arg, event_ptr)
Notify_client client;
Notify_arg arg;
Event **event_ptr;
void
win_free_event(client, arg, event)
Notify_client client;
Notify_arg arg;
Event *event;
osun
xr microsystems
Revision A, of May 9, 1988
26 Sun View 1 System Programmer’s Guide
4.4. Removing a Tile From
the Agent
The following call tells the Agent to stop managing the tile associated with
client.
int
win_unregister(client)
Notify_client client;
You should call this from the tile’s destroy_f unc that you gave to the Agent
in the win_register () call. win_unregister () also completely
removes client from having any conditions registered with the Notifier. A -1
is returned if client is not registered, otherwise 0 is returned.
Revision A, of May 9,1988
Windows
Windows. 29
5.1. Window Creation, Destruction, and Reference. 29
A New Window. 29
An Existing Window . 30
References to Windows. 30
5.2. Window Geometry. 31
Querying Dimensions. 31
The Saved Rect. 32
5.3. The Window Hierarchy. 32
Setting Window Links. 32
Activating the Window. 33
Defaults. ri
Modifying Window Relationships
Window Enumeration ...
Enumerating Window Offspring. 35
Fast Enumeration of the Window Tree. 36
5.4. Pixwin Creation and Destruction. 36
Creation. 36
Region. 32
Retained Image. 37
Bel1 . 37
Destruction. 37
5.5. Choosing Input. 37
Input Mask. 37
Manipulating the Mask Contents. 38
Setting a Mask. 38
Querying a Mask. 39
The Designee. 39
5.6. Reading Input. 39
Non-blocking Input. 39
Asynchronous Input. 39
Events Pending. 40
5.7. User Data. 40
5.8. Mouse Position . 40
5.9. Providing for Naive Programs . 41
Which Window to Use. 41
The Blanket Window. 41
5.10. Window Ownership. 42
5.11. Environment Parameters. 42
5.12. Error Handling. 43
: : : : : i : : : : ; : ; : : : : : : : : : ^xxl'^x^fev^x^xvxi
Windows
This chapter describes the facilities for creating, positioning, and controlling win¬
dows. It contains the implementation details associated with window devices, as
introduced in the SunView System Model chapter.
NOTE The recommended window programming approach is described in the SunView 1
Programmer’s Guide. You should only resort to the following window device
routines if the equivalent isn’t available at the higher level. It is possible to use
the following routines with a high level SunView Window object by passing the
file descriptor returned by
(int) window_get (Window_object, WIN_FD) ;
The structure that underlies the operations described in this chapter is maintained
within the window system, and is accessible to the client only through system
calls and their procedural envelopes; it will not be described here. The window
is presented to the client as a device-, it is represented, like other devices, by &jile
descriptor returned by open(2). It is manipulated by other UNIX system calls,
such as select(2), read(2), ioctl(2), and close(2). 5
5.1. Window Creation, As mentioned above, windows are devices. As such, they are special files in the
Destruction, and /dev directory with names of the form “/dev/win n,” where n is a decimal
Reference number. A window is created by opening one of these devices, and the window
name is simply the filename of the opened device.
A New Window The first process to open a window becomes its owner. A process can obtain a
window it is guaranteed to own by calling:
%
int
win_getnewwindow()
This finds the first unopened window, opens it, and returns a file descriptor which
refers to it. If none can be found, it returns -1. A file descriptor, often called the
windowfd, is the usual handle for a window within the process that opened it.
When a process is finished with a window, it may close it with the standard
close(2) system call with the window’s file descriptor as its argument. As with
other file descriptors, a window left open when its owning process terminates
5 The header file <sunwindow/window_hs. h> includes the header files needed to work at this level of
the window system. The library /usr /1 ib/1 ibsunwindow. a implements window device routines.
29
Revision A, of May 9,1988
30 SunView 1 System Programmer’s Guide
An Existing Window
References to Windows
will be closed automatically by the operating system.
Another procedure is most appropriately described at this point, although in fact
clients will have little use for it. To find the next available window,
win_getnewwindow () uses:
int
win_nextfree(fd)
int fd;
where f d is any valid window file descriptor. The return value is a window
number, as described in References to Windows below; a return value of
WIN_NULLLINK indicates there is no available unopened window.
It is possible for more than one process to have a window open at the same time;
the section Providing for Naive Programs below presents one plausible scenario
for using this capability. The window will remain open until all processes which
opened it have closed it The coordination required when several processes have
the same window open is described in Providing for Naive Programs.
Within the process which created a window, the usual handle on that window is
the file descriptor returned by open(2) or win_getnewwindow (). Outside
that process, the file descriptor is not valid; one of two other forms must be used.
One form is the window name (e.g. /dev/winl2); the other form is the win¬
dow number, which corresponds to the numeric component of the window name.
Both of these references are valid across process boundaries. The window
number will appear in several contexts below.
Procedures are supplied for converting among various window identifiers.
win_numbertoname () stores the filename for the window whose number is
winnumber into the buffer addressed by name:
win_numbertoname(winnumber, name)
int winnumber;
char *name;
name should be WIN_NAMESIZE long, as should all the name buffers in this
section.
win_name to number () returns the window number of the window whose
name is passed in name:
int
win_nametonumber(name)
char *name;
Given a window file descriptor, win_f dtoname () stores the corresponding
device name into the buffer addressed by name:
win_fdtoname(windowfd, name)
int windowfd;
char *name;
microsystems
Revision A, of May 9, 1988
Chapter 5 — Windows 31
win_f dtonumber () returns the window number for the window whose file *
descriptor is windowf d:
int
win_fdtonumber(windowfd)
int windowfd;
5.2. Window Geometry
Once a window has been opened, its size and position may be set. The same rou¬
tines used for this purpose are also helpful for adjusting the screen positions of a
window at other times, when the window is to be moved or stretched, for
instance. win_setrect () copies the rect argument into the rectangle of the
indicated window:
win_setrect(windowfd, rect)
int windowfd;
Rect *rect;
This changes its size and/or position on the screen. The coordinates in the rect
structure are in the coordinate system of the window’s parent. The Rects and
Rectlists chapter explains what is meant by a rect. Setting Window Links
below explains what is meant by a window’s “parent.” Changing the size of a
window that is visible on the screen or changing the window’s position so that
more of the window is now exposed causes a chain of events which redraws the
window. See the section entitled Damage in the Advanced Imaging chapter.
Querying Dimensions
The window size querying procedures are:
win__getrect (windowfd, rect)
int windowfd;
Rect *rect;
win__getsize (windowfd, rect)
int windowfd;
Rect *rect;
short win_getheight(windowfd)
int windowfd;
short win_getwidth(windowfd)
int windowfd;
w i n _J?etrect () stores the rectangle of the window whose file descriptor is
windowfd into the rect; the origin is relative to that window’s parent.
win_getsize () is similar, but the rectangle is self-relative — that is, the ori¬
gin is (0,0).
w i n _getheight () and win_getwidth () return the single requested
dimension for the indicated window — these are part of the rect structure that
the other calls return.
microsystems
Revision A, of May 9, 1988
32 SunView 1 System Programmer’s Guide
The Saved Rect
5.3. The Window
Hierarchy
Setting Window Links
A window may have an alternate size and location; this facility is useful for stor¬
ing a window’s iconic position that is associated with frames. The alternate rec¬
tangle may be read with win_get savedrect (), and written with
win_setsavedrect().
win_getsavedrect(windowfd, rect)
int windowfd;
Rect *rect;
win_setsavedrect(windowfd, rect)
int windowfd;
Rect *rect;
As with win_getrect () and win_setrect (), the coordinates are relative
to the screen.
Position in the window database determines the nesting relationships of win¬
dows, and therefore their overlapping and obscuring relationships. Once a win¬
dow has been opened and its size set, the next step in creating a window is to
define its relationship to the other windows in the system. This is done by setting
links to its neighbors, and inserting it into the window database.
The window database is a strict hierarchy. Every window (except the root) has a
parent; it also has 0 or more siblings and children. In the terminology of a family
tree, age corresponds to depth in the layering of windows on the screen: parents
underlie their offspring, and older windows underlie younger siblings which
intersect them on the display. Parents also enclose their children, which means
that any portion of a child’s image that is not within its parent’s rectangle is
clipped. Depth determines overlapping behavior: the uppermost image for any
point on the screen is the one that gets displayed. Every window has links to its
parent, its older and younger siblings, and to its oldest and youngest children.
Windows may exist outside the structure which is being displayed on a screen;
they are in this state as they are being set up, for instance.
The links from a window to its neighbors are identified by link selectors-, the
value of a link is a window number. An appropriate analogy is to consider the
link selector as an array index, and the associated window number as the value
of the indexed element. To accommodate different viewpoints on the structure
there are two sets of equivalent selectors defined for the links:
WL_PARENT == WL_ENCLOSING
WL_OLDERSIB == WL_COVERED
WL_YOUNGERSIB == WL_COVERING
WL_OLDESTCHILD == WL_BOTTOMCHILD
WL_YOUNGE S TCHILD == WL_TOPCHILD
A link which has no corresponding window, for example, a child link of a “leaf’
window, has the value WIN_NULLLINK.
When a window is first created, all its links are null. Before it can be used for
anything, at least the parent link must be set so that other routines know with
which desktop and workstation this window is to be associated. If the window is
microsystems
Revision A, of May 9,1988
Chapter 5 — Windows 33
Activating the Window
Defaults
to be attached to any siblings, those links should be set in the window as well.
The individual links of a window may be inspected and changed by the following
procedures.
win__getlink () returns a window number,
int
win_getlink(windowfd, link_selector)
int windowfd, link_selector;
This number is the value of the selected link for the window associated with
windowfd.
win_setlink(windowfd, link_selector, value)
int windowfd, link_selector, value;
w i n _setlink () sets the selected link in the indicated window to be value,
which should be another window number or WIN_NULLLINK. The actual win¬
dow number to be supplied may come from one of several sources. If the win¬
dow is one of a related group, all created in the same process, file descriptors will
be available for the other windows. Their window numbers may be derived from
the file descriptors via win_f dt onumber (). The window number for the
parent of a new window or group of windows is not immediately obvious, how¬
ever. The solution is a convention that the WINDOW_PARENT environment
parameter will be set to the filename of the parent. See
we_setparent window () for a description of this parameter.
Once a window’s links have all been defined, the window is inserted into the tree
of windows and attached to its neighbors by a call to
win_insert(windowfd)
int windowfd;
This call causes the window to be inserted into the tree, and all its neighbors to
be modified to point to it. This is the point at which the window becomes avail¬
able for display on the screen.
Every window should be inserted after its rectangle(s) and link structure have
been set, but the insertion need not be immediate: if a subtree of windows is
being defined, it is appropriate to create the window at the root of this subtree,
create and insert all of its descendants, and then, when the subtree is fully
defined, insert its root window. This activates the whole subtree in a single
action, which may result in cleaner display of the whole tree.
One need not specify all the sibling links of a window that is being inserted into
the display tree. Sibling links may be defaulted as follows (these conventions are
applied in order):
□ If the WL_COVERING sibling link is WIN_NULLLINK then the window is
put on the top of the heap of windows.
microsystems
Revision A, of May 9, 1988
34 Sun View 1 System Programmer’s Guide
Modifying Window
Relationships
□ If the WL_COVERED sibling link is WIN_NULLLINK then the window is
put on the bottom of the heap of windows.
□ If the WL_COVERED or WL_COVERING sibling links are invalid then the
window is put on the bottom of the heap of windows.
Once a window has been inserted in the window database, it is available for input
and output. At this point, it is appropriate to access the screen with pixwin calls
(to draw something in the window!).
Windows may be rearranged in the tree. This will change their overlapping rela¬
tionships. For instance, to bring a window to the top of the heap, it should be
moved to the “youngest” position among its siblings. And to guarantee that it is
at the top of the display heap, each of its ancestors must likewise be the youngest
child of its parent.
To accomplish such a modification, the window should first be removed:
win_remove(windowfd)
int windowfd;
After the window has been removed from the tree, it is safe to modify its links,
and then reinsert it.
A process doing multiple window tree modifications should lock the window tree
before it begins. This prevents any other process from performing a conflicting
modification. This is done with a call to:
win_lockdata(windowfd)
int windowfd;
After all the modifications have been made and the windows reinserted, the lock
is released with a call to:
win_unlockdata(windowfd)
int windowfd;
Nested pairs of calls to lock and unlock the window tree are permitted. The final
unlock call actually releases the lock.
If a client program uses any of the window manager routines, use of
win_lockdata () and win_unlockdata () is not necessary. See the
chapter on Window Management for more details.
Most routines described in this chapter, including the four above, will block tem¬
porarily if another process either has the database locked, or is writing to the
screen, and the window adjustment has the possibility of conflicting with the
window that is being written.
As a method of deadlock resolution, SIGXCPU is sent to a process that spends
more that 2 seconds of process virtual time inside a window data lock, and the
lock is broken. 6
6 The section Kernel Tuning Options in the Workstation chapter describes how to modify this default
number of seconds (see ws_lock_limit).
Revision A, of May 9,1988
Chapter 5 — Windows 35
Window Enumeration There are routines that pass a client-defined procedure to a subset of the tree of
windows, and another that returns information about an entire layer of the win¬
dow tree. They are useful in performing window management operations on
groups of windows. The routines and the structures they use and return are listed
in <sunwindow/win_enum.h>.
Enumerating Window Offspring The routines win_enumerate_children () and
win_enumerate_subtree () repeatedly call the client’s procedure passing
it the windowfds of the offspring of the client window, one after another:
enum win__enumerator_resuit
win__enumerate_children (windowfd, proc, args) ;
Window__handle windowfd;
Enumerator proc;
c a ddr_t args;
enum win_enumerator_result
win_enumerate_subtree(windowfd, proc, args);
Window_handle windowfd;
Enumerator proc;
caddr__t args;
enum win__enumerator_result \
{ Enum_Norma 1, Enum__Succeed, Enum_Fail };
typedef enum win_enumerator_result
(^Enumerator)();
windowfd is the window whose children are enumerated (Window_handle is
typedef ’d to int). Both routines repeatedly call proc (), stopping when
told to by proc () or when everything has been enumerated.
proc () is passed a windowfd and args
(*proc)(fd, args);
It does whatever it wants with the windowfd, then returns
win_enumerator_result. If proc () returns Enum_Norma 1 then the
enumeration continues; if it returns Enum_Succeed or Enum_Fail then the
enumeration halts, and win_enumerate_children or
w in_enumerate_subtree () returns the same result.
The difference between the two enumeration procedures is that
win _enumerate_children () invokes proc ( ) with an fd for each
immediate descendant of windowfd in oldest-to-youngest order, while
win_enumerate_subtree ( ) invokes proc () with a windowfd for the
original window windowfd and for all of its descendants in depth-first, oldest-
to-youngest order. The former enumerates windowf d’s children, the latter
enumerates windowfd and its extended family.
It is possible that win_enumerate_subtree () can run out of file descrip¬
tors during its search of the tree if the descendants of windowfd are deeply
nested.
Revision A, of May 9,1988
36 SunView 1 System Programmer’s Guide
Fast Enumeration of the
Window Tree
5.4. Pixwin Creation and
Destruction
Creation
The disadvantage with the above two routines is that they are quite slow. They
traverse the window tree, calling win_get link () to find the offspring, then
open each window, then call the procedure.
In 3.2 there is a fast window routine, win_get_tree_layer (), that returns
information about all the children of a window in a single ioctl^:
win_get_tree_layer(parent, size, buffer);
Window_handle parent;
u_int size;
char *buffer;
typedef struct win_enum_node {
unsigned char me;
unsigned char parent;
unsigned char upper_sib;
unsigned char lowest_kid;
unsigned int flags;
#define WIN_NODE_INSERTED Oxl
#define WIN_NODE_OPEN 0X2
♦define WIN_NODE_IS_ROOT 0x4
Rect open_rect;
Rect icon_rect;
) Win_enum_node;
win_get_tree_layer () fills buffer with Win_enum_node informa¬
tion (rects, user flags, and minimal links) for the children of window in oldest-
to-youngest order. It returns the number of bytes of buff er filled with infor¬
mation, or negative if there is an error.
Unlike win_enumerate_children (), win_get_tree_layer ()
returns information for all the children of windowf d including those that are
have not been installed in the window tree with win_insert () ; such children
will not have the WlN_NODE_INSERTED flag set.
A pixwin is the object that you use to access the screen. Its usage has been
covered in the Imaging Facilities: Pixwins chapter of the SunView Programmer’s
Guide and in the previous chapter on tiles. How to create a pixwin region has
also been covered in the same places. Here we cover how a pixwin is generated
for a window.
To create a pixwin, the window to which it will refer must already exist. This
task is accomplished with procedures described earlier in this chapter. The
pixwin is then created for that window by a call to pw_open ():
Pixwin *
pw_open(windowfd)
int windowfd;
pw_open () takes a file descriptor for the window on which the pixwin is to
7 win_get_t ree layer ( ) will use the slower method if the kernel does not support the ioctl; thus
programs that use this can be run on 3.0 systems.
microsystems
Revision A, of May 9,1988
Chapter 5 — Windows 37
Region
Retained Image
Bell
Destruction
5.5. Choosing Input
Input Mask
write. A pointer to a pixwin struct is returned. At this point the pixwin describes
the exposed area of the window.
To create the pixwin for a tile, call pw_region () passing it the pixwin
returned from pw_open ().
If the client wants a retained pixwin, the pw_jprretained field of the pixwin
should be set to point to a memory pixrect of your own creation. If you set this
field you need to call pw_exposed (pw) afterwards. 8 This updates the
pixwin’s exposed area list to deal with the memory pixrect; see the Advanced
Imaging chapter for more information on pw_expose ().
The following routine can be used to beep the keyboard bell and flash a pixwin:
win_bell(windowfd, wait_tv, pw)
int windowfd;
struct timeval wait_tv;
Pixwin *pw;
If pw is 0 then there is no flash. wait_t v controls the duration of the bell. 9
When a client is finished with a pixwin, it should be released by a call to:
pw__close (pw)
Pixwin *pw;
pw_close () frees any resource associated with the pixwin, including its
pw_prretained pixrect if any. If the pixwin has a lock on the screen, it is
released.
The chapter entitled Handling Input in the SunView Programmer*s Guide
describes the window input mechanism. This section describes the file descriptor
level interface to setting a window’s input masks. This section is very terse,
assuming that the concept from Handling Input are well understood.
Clients specify which input events they are prepared to process by setting the
input masks for each window being read. The calls in this section manipulate
input masks.
8 The best way to manage a retained window is to let the Agent do it (see win register ()).
9 The bell’s behavior is controlled by the SunView de fault sedit entries SunView!Audible Bell and
Sunview/Visible_Bell y so the sound and flash can be disabled by the user, regardless of what the call to
win_bell() specifies.
Revision A, of May 9, 1988
38 SunView 1 System Programmer’s Guide
Manipulating the Mask
Contents
Setting a Mask
typedef struct inputmask {
short im__flags;
#define
IM_
NEGEVENT
(0x01)
/*
#define
IM_
[ascii
(0x10)
/*
#define
IM_
[meta
(0x20)
/*
#define
IM_
_NEGASCII
(0x40)
/*
#define
IM_
_NEGMETA
(0x80)
/*
#define
IM_
_INTRANSIT
(0x400)
/*
} Inputmask;
send input negative events too */
enable ASCII codes 0-127 */
enable META codes 128-255 */
enable negative ASCII codes 0-127 */
enable negative META codes 128-255 *,
don't surpress locator events when
in-transit over window */
The bit flags defined for the input mask are stored directly in the im_f lags
field. To set a particular event in the input mask use the following macro:
win_setinputcodebit(im, code)
Inputmask *im;
u_short code;
win_setinputcodebit () sets a bit indexed by code in the input mask
addressed by im to 1.
win__unsetinputcodebit (im, code)
Inputmask *im;
u_short code;
win_unsetinputcodebit () resets the bit to zero.
The following macro is used to query the state of an event code in an input mask:
int
win_getinputcodebit(im, code)
Inputmask *im;
u_short code;
win_getinputcodebit () returns non-zero if the bit indexed by code in
the input mask addressed by im is set.
input_imnull () initializes an input mask to all zeros:
input__imnull (im)
Inputmask *im;
It is critical to initialize the input mask explicitly when the mask is defined as a
local procedure variable.
The following routines set the keyboard and pick input masks for a window. The
different types of masks are discussed in the Input chapter.
win_set_kbd_mask(windowfd, im)
int windowfd;
Inputmask *im;
win_set_pick_mask(windowfd,
int windowfd;
Inputmask *im;
im)
microsystems
Revision A, of May 9, 1988
Chapter 5 — Windows 39
Querying a Mask
The Designee
5.6. Reading Input
Non-blocking Input
Asynchronous Input
The following routines get the keyboard and pick input masks for a window.
win_get__kbd_mask (windowfd, im)
int windowfd;
Inputmask *im;
win_get_pick_mask(windowfd, im)
int windowfd;
Inputmask *im;
The designee is that window that input is directed to if the input mask for a win¬
dow doesn’t match a particular event:
win_get_designee(windowfd, nextwindownumber)
int windowfd, *nextwindownumber;
win_set__designee (windowfd, nextwindownumber)
int windowfd, nextwindownumber;
The recommended way of getting input is to let the Agent notify you of input
events (see chapter on tiles). However, there are times when you may want to
read input directly, say, when tracking the mouse until one of its buttons goes up.
A library routine exists for reading the next input event for a window:
int
input_readevent(windowfd, event)
int windowfd;
Event *event;
This fills in the event struct, and returns 0 if all went well. In case of error, it
sets the global variable errno, and returns -1; the client should check for this
case.
A window can be set to do either blocking or non-blocking reads via a standard
f cntl(2) system call, as described in f cntl(2) (using _SETFL) and
fcntl(5) (using FNDELAY). A window defaults to blocking reads. The block¬
ing status of a window can be determined by the f cntl(2) system call.
When all events have been read and the window is doing non-blocking I/O,
i nput_readevent () returns -1 and the global variable errno is set to
EWOULDBLOCK.
A window process can ask to be sent a SIGIO if any input is pending in a win¬
dow. This option is also enabled via a standard f cntl(2) system call, as
described in f cntl(2) (using F_SETFL) and f cntl(5) (using FASYNC). The
programmer can set up a signal handler for SIGIO by using the
notify_set_signal_func () call. 10
10 The Notifier handles asynchronous input without you having to set up your own signal handler if you are
using the Notifier to determine when there is input for a window.
microsystems
Revision A, of May 9,1988
40 SunView 1 System Programmer’s Guide
Events Pending
5.7. User Data
5.8. Mouse Position
The number of character in the input queue of a window can be determined via a
FBIONREAD ioctl(2) call. FBIONREAD is described in tty(4). Note that
the value returned is the number of bytes in the input queue. If you want the
number of Events then divide by sizeof (Event).
Each window has 32 bits of data associated with it. These bits are used to imple¬
ment a minim al inter-process window-related status-sharing facility. Bits 0x01
through 0x08 are reserved for the basic window system; 0x01 is currently used to
indicate if a window is a blanket window. Bits 0x10 through 0x80 are reserved
for the user level window manager; 0x10 is currently used to indicate if a win¬
dow is iconic. Bits 0x100 through 0x80000000 are available for the
programmer’s use. They is manipulated with the following procedures:
int
win_getuserflags(windowfd)
int windowfd;
int
win_setuserflags(windowfd, flags)
int windowfd;
int flags;
int
win_setuserflag(windowfd, flag, value)
int windowfd;
int flag;
int value;
win_getuserflags () returns the user data. win_setuserflags ()
stores its flags argument into the window struct. win_setuserf lag ()
uses flag as a mask to select one or more flags in the data word, and sets the
selected flags on or off as value is TRUE or FALSE.
Determining the mouse’s current position is treated in the SunView
Programmer’s Guide. The convention for a process tracking the mouse is to
arrange to receive an input event every time the mouse moves; the mouse posi¬
tion is passed with every user input event a window receives.
The mouse position can be reset under program control; that is, the cursor can be
moved on the screen, and the position that is given for the mouse in input events
can be reset without the mouse being physically moved on the table top.
win_setmouseposition(windowfd, x, y)
int windowfd, x, y;
win_setmouseposition () puts the mouse position at (x, y) in the coordi¬
nate system of the window indicated by windowfd. The result is a jump from
the previous position to the new one without touching any points between. Input
events occasioned by the move, such as window entry and exit and cursor
changes, will be generated. This facility should be used with restraint, as many
users are unhappy with a cursor that moves independent of their control.
Occasionally it is necessary to discover which window underlies the cursor, usu¬
ally because a window is handling input for all its children. The procedure used
#sun Revision A, of May 9,1988
microsystems
Chapter 5 — Windows 41
for this purpose is:
int
win_findintersect(windowfd, x, y)
int windowfd, x, y;
where windowfd is the calling window’s file descriptor, and (x, y) defines a
screen position in that window’s coordinate space. The returned value is a win¬
dow number of a child of the calling window. If a child of the calling window
doesn’t fall under the given position WIN_NULLLINK is returned.
5.9. Providing for Naive There is a class of applications that are relatively unsophisticated about the win-
Programs dow system, but want to run in windows anyway. For example, a graphics pro¬
gram may want a window in which to ran, but doesn’t want to know about all the
details of creating and positioning it. This section describes a way of allowing
for these applications.
Which Window to Use The window system defines an important environment parameter,
WlNDOW_GFX. By convention, WINDOW_GFX is set to a string that is the dev¬
ice name of a window in which graphics programs should be run. This window
should already be opened and installed in the window tree. Routines exist to
read and write this parameter:
int
we_getgfxwindow(name)
char *name
we_setgfxwindow(name)
char *name
we_getgf xwindow () returns a non-zero value if it cannot find a value.
The Blanket Window A good way to take over an existing window is to create a new window that
becomes attached to and covers the existing window. Such a covering window is
called a blanket window. The covered window will be called the parent window
in this subsection because of its window tree relationship with a blanket win¬
dow. 11
The appropriate way to make use of the blanket window facility is as follows:
Using the parent window name from the environment parameter WINDOW_GFX
(described above), open(2) the parent window. Get a new window to be used as
the blanket window using win_getnewwindow (). Now call:
int
win_insertblanket(blanketfd, parentfd)
int blanketfd, parentfd;
A zero return value indicates success. As the parent window changes size and
position the blanket window will automatically cover the parent.
11 It’s a bad idea to take over an existing window using win set owner ().
microsystems
Revision A, of May 9, 1988
42 SunView 1 System Programmer’s Guide
To remove the blanket window from on top of the parent window call:
win_removeblanket(blanketfd)
int blanketfd;
If the process that owns the window over which the blanket window resides dies
before win_removeblanket () is called, the blanket window will automati¬
cally be removed and destroyed.
A non-zero return value from win_isblanket () indicates that blanketfd
is indeed a blanket window.
int
win_isblanket(blanketfd)
int blanketfd;
5.10. Window Ownership SIGWINCH signals are directed to the process that owns the window, the owner
normally being the process that created the window. The following procedures
read from and write to the window: 12 These routines are included for backwards
compatibility.
int
win_getowner(windowfd)
int windowfd;
win_setowner(windowfd, pid)
int windowfd, pid;
win_getowner () returns the process id of the indicated window owner. If
the owner doesn’t exist, zero is returned. win_setowner () makes the process
identified by pid the owner of the window indicated by windowfd.
win_setowner causes a SIGWINCH to be sent to the new owner.
5.11. Environment Environment parameters are used to pass well-established values to an applica-
Parameters tion. They have the valuable property that they can communicate information
across several layers of processes, not all of which have to be involved.
Every frame must be given the name of its parent window. A frame’s parent
window is the window in the display tree under which the frame window should
be displayed. The environment parameter WlNDOW_PARENT is set to a string
that is the device name of the parent window. For a frame, this will usually be
the name of the root window of the window system.
we_setparentwindow(windevname)
char *windevname;
sets WINDOW PARENT to windevname.
12 Do not use the two routines in this section for temporarily talcing over another window.
V microsystems
Revision A, of May 9,1988
Chapter 5 — Windows 43
int
we_getparentwindow(windevname)
char *windevname;
gets the value of WINDOW_PARENT into windevname. The length of this
string should be at least WIN_NAMESIZE characters long, a constant found in
<sunwindow/win_struct . h>. A non-zero return value means that the
WINDOW_PARENT parameter couldn’t be found.
The environment parameter DEFAULT_FONT should contain the font file name
used as the program’s default (see pf_def ault ()).
NOTE This is retained for backwards compatibility. All programs set this variable , but
only old-style SunWindows programs , gfx subwindow programs and raw pixwin
programs use it to determine which font to use. SunView programs that don t set
their own font use the SunView/Font defaults entry; you can use the -Wt
fontname command line frame argument to change the font of SunView programs
that allow it.
5.12. Error Handling Except as explicitly noted, the procedures described in this section do not return
error codes. The standard error reporting mechanism inside the sunwindow
library is to call an error handling routine that displays a message, typically iden¬
tifying the ioct 1(2) call that detected the error. This error message is some¬
what cryptic; Appendix B, Programming Notes , has a section on Error Message
Decoding . After the message display, the calling process resumes execution.
This default error handling routine may be replaced by calling:
int (*win_errorhandler(win_error))()
int (*win_error)();
The win_errorhandler () procedure takes the address of one procedure, the
new error handler, as an argument and returns the address of another procedure,
the old error handler, as a result. Any error handler procedure should be a func¬
tion that returns an integer.
win_error(errnum, winopnum)
int errnum, winopnum;
errnum will be -1 indicating that the actual error number is found in the global
err no. winopnum is the ioct 1(2) number that defines the window operation
that generated the error. See Section B.4, Error Message Decoding , in Appendix
B, Programming Notes.
microsystems
Revision A, of May 9, 1988
Desktops
Desktops
47
Look at sunview.
6.1. Multiple Screens.
The singlecolor Structure.
The screen Structure
Screen Creation.
Initializing the screen Structure
Screen Query.
Screen Destruction.
Screen Position.
Accessing the Root FD.
47
47
47
48
48
49
49
49
49
50
Desktops
This chapter discusses the calls that affect the screen, or desktop. Some calls
affect workstation-related data, i.e., global input related data. This overlap of the
conceptual model is purely historical.
Look at sunview Many of the routines in here are used by Sun’s window manager, sunview(l).
You will find it very helpful to look at the source for sunview (it is optional
software that must be loaded in suninstall) to see how it uses these routines.
6.1. Multiple Screens Workstations may use multiple displays, and clients may want windows on all of
them. 13 Therefore, the window database is a forest, with one tree of windows for
each display. There is no overlapping of window trees that belong to different
screens. For displays that share the same mouse device, the physical arrange¬
ment of the displays can be passed to the window system, and the mouse cursor
will pass from one screen to the next as though they were continuous.
The singlecolor Structure The screen structure describes attributes of the display screen. First, here is
the definition of singlecolor, which it uses for the foreground and back¬
ground colors:
struct singlecolor {
u_char red, green, blue;
1;
There can be as many screens as there are frame buffers on your machine and dlop pseudo devices
configured into your kernel. The kernel calls screen instances dtops.
&sun
microsystems
47
Revision A, of May 9, 1988
48 SunView 1 System Programmer’s Guide
The screen Structure
Screen Creation
Now the screen structure:
struct screen
{
char
scr rootname [SCR__NAMESIZE] ;
char
scrjcbdname [SCR_NAMESIZE] ;
char
scr msname[SCR_NAMESIZE];
char
scr fbname[SCR_NAMESIZE];
struct
singlecolor scr_foreground;
struct
singlcolor scr_background;
int
scr_flags;
struct
};
rect scr__rect;
♦define SCR_NAMESIZE 20
♦define SCR_SWITCHBKGRDFRGRD 0x1
scr_rootname is the device name of the window which is at the base of the
window display tree for the screen; it is often /dev/winO , 14 scr_kbdname is
the device name of the keyboard associated with the screen; the default is
/dev/kbd. scr_msname is the device name of the mouse associated with the
screen; the default is /dev/mouse. scr_fbname is the device name of the
frame buffer on which the screen is displayed; the default is / dev/ f b for the
first desktop. scr_kbdname, scr_msname and scr_fbname can have the
string “NONE” if no device of the corresponding type is to be associated with the
screen. Workstations (hence also desktops) can have additional input devices
associated with them; see the section on User Input Device Control in the Works¬
tations chapter.
scr_f oreground is three RGB color values that define the foreground color
used on the frame buffer; the default is { colormap size-1, colormap size-1,
colormap size-1 }. scr_background is three RGB color values that define
the background color used on the frame buffer; the default is {0, 0, 0}. The
default values of the background and foreground yield a black on white image,
serf lags contains boolean flags; the default is 0.
SCR_SWITCHBKGRDFRGRD is a flag that directs any client of the background
and foreground data to switch their positions, thus providing a video reversed
image (usually yielding a white on black image). scr_rect is the size and
position of the screen on the frame buffer; the default is the entire frame buffer
surface.
To create a new screen call:
int
win_screennew(screen)
struct screen ‘screen;
14 Multiple screen configurations, in particular, will not have /dev/winO as the root window on the second
screen.
microsystems
Revision A, of May 9, 1988
Chapter 6 — Desktops 49
Initializing the screen
Structure
Screen Query
Screen Destruction
Screen Position
win__screennew ( ) opens and returns a window file descriptor for a root
desktop window. This new root window resides on the new screen which was
defined by the specifications of screen. Any zeroed field in screen tells
win_screennew () to use the default value for that field (see above for
defaults). Also, see the description of win_initscreenf romargv ()
below. If—1 is returned, an error message is displayed to indicate that there was
some problem creating the screen.
The following routine can be called before calling win_screennew ():
int
win_initscreenfromargv(screen, argv)
struct screen ‘screen;
char **argv;
win_initscreenf romargv () zeroes the ‘screen structure, then it parses
the relevant command line arguments in argv into * screen. You then call
win_screennew () to creates a root window with the desired attributes. The
command line arguments allow the user to set all the variables in ‘screen
including the display device, the keyboard device, the mouse device, the fore¬
ground and background colors, whether the screen colors should be inverted, and
other features. See sunview(l) for semantics and details.
To find out about the screen on which your window is running call:
win_screenget(windowfd, screen)
int windowfd;
struct screen ‘screen;
w i n __screenget () fills in the addressed struct ‘screen with information
for the screen with which the window indicated by windowfd is associated.
You can call this from any window.
To destroy the screen on which your window is running call:
win_screendestroy(windowfd)
int windowfd;
w i n _screendestroy () causes each window owner process (except the
invoking process) on the screen associated with windowfd to be sent a
SIGTERM signal. This call will block until all the processes have died. If a win¬
dow owner process hasn’t gone away after 15 seconds, it is sent a SIGKILL,
which will destroy it.
To tell the window system how multiple screens are arranged call:
Revision A, of May 9,1988
50 SunView 1 System Programmer’s Guide
win setscreenpositions(windowfd, neighbors)
int windowfd, neighbors[SCR_POSITIONS];
#define SCR_NORTH 0
tdefine SCRJEAST 1
#define SCR_SOUTH 2
#define SCR_WEST 3
#define SCR_POSITIONS 4
win__set screenpositions () informs the window system of the logical
layout of multiple screens. This enables the cursor to cross to the appropriate
screen, windowf d’s window is the root for its screen; the four slots in neigh¬
bors should be filled in with the window numbers of the root windows for the
screens in the corresponding positions. No diagonal neighbors are defined, since
they are not strictly neighbors.
win__getscreenpositions () fills in neighbors with windowf d’s
screen’s neighbors:
win_getscreenpositions(windowfd, neighbors)
int windowfd, neighbors[SCR_POSITIONS];
CAUTION In these routines, windowfd must be an fd for the root window. Most
operations on the screen can be done using any windowfd.
Accessing the Root FD The following code fragment gets the screen struct for your window, then
opens the window device of the root window:
-—-—-\
int mywinfd, rootfd;
struct screen rootscreen;
win__screenget (mywinfd, &rootscreen) ;
rootfd = open(rootscreen.scr_rootname);
XT microsystems
Revision A, of May 9, 1988
Workstations
Workstations. 53
7.1. Virtual User Input Device. 53
What Kind of Devices?. 53
Vuid Features. 54
Vuid Station Codes. 54
Address Space Layout. 54
Adding a New Segment. 55
Input State Access. 55
Unencoded Input. 55
7.2. User Input Device Control . 56
Distinguished Devices . 56
Arbitrary Devices. 57
Non-Vuid Devices. 57
Device Removal. 57
Device Query... 57
Device Enumeration. 58
7.3. Focus Control. 58
Keyboard Focus Control. 58
Event Specification. 59
Setting the Caret Event. 59
Getting the Caret Event. 59
Restoring the Caret. 59
7.4. Synchronization Control. 60
Releasing the Current Event Lock... 60
Current Event Lock Breaking.;... 60
Getting/Setting the Event Lock Timeout. 61
7.5. Kernel Tuning Options. 61
Changing the User Actions that Affect Input. 63
Workstations
This chapter discusses the manipulation of workstation data, which comprises
mostly global data related to input and input devices. Some calls in the Desktops
chapter also affect workstations. This overlap is purely historical. This chapter
also explains parts of the Virtual User Input Device interface that were not
covered in the Handling Input chapter of the SunView 1 Programmer’s Guide.
That chapter gave the possible event codes in SunView 1; this chapter explains
the mechanism which sets up input devices to generate them.
7.1. Virtual User Input The Virtual User Input Device ( vuid) is an interface between input devices and
Device their clients. The interface defines an idealized user input device that may not
correspond to any existing physical collection of input devices. A client of Sun¬
View doesn’t access vuid devices directly. Instead, the window system reads
vuid devices, serializing input from all the vuid devices and then makes the input
available to windows as SunView vuid events.
NOTE You don’t have to write a vuid interface to use your own device in SunView: you
can use any input device that generates ASCII. But if your device is hooked up
using vuid, then your SunView programs can interface with it using the SunView
input event mechanism.
Since SunView’s input system is built on top of vuid, it is explained in some
detail.
What Kind of Devices? Vuid is targeted to input devices that gather command data from humans, e.g.,
mice, keyboards, tablets, joysticks, light pens, knobs, sliders, buttons, ascii termi¬
nals, etc. 15 The vuid interface is not designed to support input devices that pro¬
duce voluminous amounts of data, such as input scanners, disk drives, voice
packets.
Here are some of the properties that are expected of a typical client of vuid, e.g.,
SunView:
□ The client has a richer user interface than can be supported by a simple
ASCII terminal.
15 The appendix titled Writing a Virtual User Input Device Driver discusses how to write a device driver
that speaks the vuid protocol for a new input device.
microsystems
53
Revision A, of May 9,1988
54 SunView 1 System Programmer’s Guide
Vuid Features
Vuid Station Codes
Address Space Layout
□ The client serializes multiple input devices being used by the user into a sin¬
gle stream of events.
□ The client preserves the entire state of its input so that it may query this
state.
Vuid provides, among others, the following services to clients:
□ A client may extend the capabilities of the predefined vuid by adding input
devices. A client wants to be able to do this in a way that fits smoothly with
its existing input paradigm.
□ A client’s code may be input device independent. A client can replace the
physical device(s) underlying the virtual user input device and not have to
change any input or event handlers, only the input device driver. In fact, the
vuid interface doesn’t care about physical devices. One physical device can
masquerade as many logical devices and many physical devices can look
like a single logical device.
This section defines the layout of the address space of vuid station codes. It
explains how to extend the vuid address space for your own purposes. The
meaning of vuid station codes is covered in the Handling Input chapter of the
SunView 1 Programmer’s Guide. The programmatic details of the vuid interface
are covered in Writing a Virtual User Input Device Driver appendix to this docu¬
ment,
The address space for vuid events is 16 bits long, from 0 to 65535 inclusive. It is
broken into 256 segments that are 256 entries long (VUID_SEG_SIZE). The
top 8 bits contain a vuid segment identifier value. The bottom 8 bits contain a
segment specific value from 0 to 255. Some segments have been predefine and
some are available for expansion. Here is how the address space is currently bro¬
ken down:
□ ASCII_DEVID (0x00) — ASCII codes, which include META codes.
□ TOP_DEVID (0x01) — Top codes, which are ASCII with the 9th bit on.
o Reserved (0x02 to 0x7B) — for Sun vuid implementations.
□ SUNVIEW_DEVID (0x7C) — SunView semantic “action” events generated
inside SunView by keymapping.
□ P ANEL_DEVID (0x7D) — Panel subwindow package event codes used
internally in the panel package (see <suntool/panel. h>).
o SCROLL_DEVlD (0x7E) — Scrollbar package event codes passed to
scrollbar clients on interesting scrollbar activity (see
<suntool/scrollbar. h>).
Asun
\r microsystems
Revision A, of May 9, 1988
Chapter 7 — Workstations 55
This device is a bit of a hodge¬
podge for historical reasons; the
middle of the address space has
SunView-related events in it (see
<sunwindow/win_input. h>),
and the virtual keyboard and virtual
locator are thrown together.
Adding a New Segment
NOTE
Input State Access
Unencoded Input
□ WORKSTATION_DEVID (0x7F) — Virtual keyboard and locator (mouse)
related event codes that describe a basic "workstation" device collection (see
<sundev/vuid_event .h>).
□ Reserved for Sun customers (0x80 to OxFF) — if you are writing a new vuid,
you can use a segment in here; see the next section.
<sundev/vuid_event. h> is the central registry of virtual user input dev¬
ices. To allocate a new vuid you must modify this file:
□ Choose an unused portion of the address space. Vuids from 0x00 to 0x7F
are reserved for use by Sun. Vuids from 0x80 to OxFF are reserved for Sun
customers.
□ Add the new device with a *_DEVID #def ine in this file. Briefly
describe the purpose/usage of the device. Mention the place where more
information can be found.
□ Add the new device to the Vuid_device enumeration with a
VUID _devname entry.
o List the specific event codes in another header file that is specific to the new
device. ASCII_DEVID, TOP_DEVID and WORKSTATION_DEVID events
are listed in <sundev/vuid_event. h> for historical reasons.
A new vuid device can just as easily be a pure software construction as it can be
a set of unique codes emitted by a new physical device driver.
The complete state of the virtual input device is available. For example, one can
ask questions about the up/down state of arbitrary keys.
int
win_get_vuid_value(windowfd, id)
int windowfd;
short id;
id is one of the event codes from <sundev/vuid event . h> or
<sunwindow/win_input . h>. windowfd can be any window file descrip¬
tor.
The result returned for keys is 0 for key is up and 1 for key is down; some vuid
events return a range of numbers, such as mouse position. There is no error code
for “no such key” because, by definition, the vuid event address space is the
entire range of shorts and therefore you can’t ask an incorrect question. 0 is
the default event state.
Unencoded keyboard input is supported, for those customers who cannot use the
normal keyboard input mechanism .
A new keyboard translation was introduced in 3.2. The type of translation is set
by the KIOCTRANS ioctl (see kb(4S) and kbd(4S)). Old values were:
This device is a bit of a hodge¬
podge for historical reasons; the
middle of the address space has
SunView-related events in it (see
<sunwindow/win_input. h>),
and the virtual keyboard and virtual
locator are thrown together.
Adding a New Segment
NOTE
Input State Access
Unencoded Input
Revision A, of May 9,1988
56 Sun View 1 System Programmer’s Guide
TR_NONE
TR_ASCII
TR EVENT
for unencoded keyboard input outside the window sys¬
tem
for ASCII events (characters and escape sequences) out¬
side the window system
for window input events inside the window system
A new value is now supported:
TR_UNTRANS_EVENT
gives unencoded keyboard values for input events inside the win¬
dow system.
The client must have WIN_ASCII_EVENTS set in the window’s input mask; if
up-transitions are desired, WIN_UP_ASCII_EVENTS must also be set. (See
Chapter 6, Handling Input, in the SunView Programmer’s Guide for how to set
input masks.)
The number of the key pressed or released will be passed in the event’s id
ie_code, and the direction of the transition will be reported correctly by
event_is_up () and event__is_down () (i.e., the NEGEVENT flag in
ie_f lags will be correct). The state of the shiftmask is undefined.
Events for other input (e.g. from the mouse) will be merged in the same stream
with keyboard input, in standard window input fashion.
NOTE Setting the keyboard translation has a global effect—it is not possible to get
encoded input in one window and unencoded input in another on the same
workstation.
7.2. User Input Device
Control
The number and kind of physical user input devices that can be used to drive
SunView is open ended. Here are the controls for manipulating those devices.
Distinguished Devices
A keyboard and a mouse-like device are distinguished and settable directly. The
Desktops chapter describes how they are specified in the screen structure.
Here are two calls for changing them explicitly.
int
win_setkbd(windowfd, screen)
int windowfd;
struct screen *screen;
changes the keyboard associated with windowf d’s desktop. Only the data per¬
tinent to the keyboard is used (i.e., screen->scr_kbdname).
int
win_setms(windowfd, screen)
int windowfd;
struct screen *screen;
changes the mouse associated with windowf d’s desktop. Only the data per¬
tinent to the mouse is used (i.e., screen->scr_msname).
®sun
\T microsystems
Revision A, of May 9, 1988
Chapter 7 — Workstations 57
Arbitrary Devices
Non-Vuid Devices
Device Removal
Device Query
Arbitrary user input devices may be used to drive a workstation. However, some
care must be exercised in selecting the combinations of devices. To install an
input device with SunView, call win_set_input_device ().
int
win__set_input__device (windowfd, inputfd, name)
int windowfd;
int inputfd;
char *name;
windowfd identifies (by association) the workstation on which the input device
is to be installed, name is used to identify the device on subsequent calls to Sun-
View, e.g., Idevlkbd. name may only be SCRJNAMESIZE characters long.
Before calling this routine, open the input device and make any ioctl(2) calls
to it to set it up to your requirements, e.g. possibly setting the speed of the serial
port through which the device in coming in on. Pass the open file descriptor in as
inputfd.
win_set_input_device () sends additional ioctl(2) calls to make the
device operate as a Virtual User Input Device (if that is not its native mode) and
operate in non-blocking read mode. The device’s unread input is flushed. Sun-
View starts reading from the device. Once win_set_input_device ()
returns, close inputfd. This action won’t actually close the device; SunView
has its own open file descriptor for the device.
User input devices that only emit ASCII, and not vuid events, may be used by
SunView. If the device does not respond to probing with the vuid ioctls Sun¬
View assumes it is an ASCII device and reads it one character at a time.
Thus, SunView can handle input from a simple ASCII terminal without
modification to any drivers. The routines in the section can be used with vuid or
ASCII devices.
To remove an input device from SunView, call
win_remove_input_device().
int
win_remove_input_device(windowfd, name)
int windowfd;
char *name;
windowfd identifies the workstation from which to remove the input device,
name identifies the device. SunView resets the device to its original state.
To ask if an input device is being utilized by a workstation, call
win_is_input_device().
int
win_is_input_device(windowfd, name)
int windowfd;
char *name;
windowfd identifies the workstation being probed, name identifies the device.
0 is returned if the device is not being utilized, 1 is returned if it is, and -1 is
microsystems
Revision A, of May 9, 1988
58 SunView 1 System Programmer’s Guide
Device Enumeration
7.3. Focus Control
Keyboard Focus Control
returned if there is an error.
To ask what all the input devices of the workstation are, call
win enum input_device () which enumerates them all.
int
win_enum_input_device(windowfd, func, data)
int windowfd;
int (*func)();
caddr_t data;
windowfd identifies the workstation being probed. You pass the function
func which is called once for every input device. The first argument passed to
func () is a string which is the name of the device. The second argument
passed to func () is data, which can be anything you want. If func returns
something other than 0 the enumeration is terminated early.
win_enum_input_device () returns -1 if there was an error during the
enumeration, 0 if it went smoothly and 1 if func terminated the enumeration
early.
The concept of a split keyboard and pick input focus has been described in the
SunView 1 Programmer’s Guide. The user interface documentation describes it
as ’’click to type” mode. It allows keyboard input events to be directed to a dif¬
ferent window than the window that pick (cursor) inputs are sent to. Usually you
want the keyboard input focus to stay in one window while the pick input focus
is the window under the cursor.
The following routine is called when a window gets a KBD_REQUEST event and
the window doesn’t need the keyboard focus.
win_refuse_kbd_focus(windowfd)
int windowfd;
The following routine is used to change the keyboard focus. It is only a hint; the
target window can refuse the keyboard focus or the user may not be running in
click-to-type mode.
int
win_set_kbd_focus(windowfd, number)
int windowfd, number;
number is the window that you want to have the keyboard focus.
The following routine gets the window number of the window that is currently
the keyboard focus.
int
win_get_kbd_focus(windowfd)
int windowfd;
#sun
microsystems
Revision A, of May 9, 1988
Chapter 7 — Workstations 5 9
Event Specification
Setting the Caret Event
Getting the Caret Event
Restoring the Caret
This section describes how to programmatically specify which user actions are
used as the focus control actions. The sunview(l) program has a set of flags to
control the keyboard focus.
One of the ways to change the keyboard focus is to set the caret. Setting the
focus passes the focus change event through to the application.
void
win_set_focus_event(windowfd, fe, shifts)
int windowfd;
Firm_event *fe;
int shifts;
windowfd identifies the workstation, f e is a firm event pointer; the entire
Firm_event structure is defined in the appendix titled Writing a Virtual User
Input Device Driver . Only the id and the value fields are utilized in this call.
The id field of *f e is set to the identifier of the event that is used to set the key¬
board focus, e.g., MS_LEFT. The value field is set to the value of the event
that is used to set the keyboard focus, e.g., 0 (up) or 1 (down), shifts is a
mask of shift bits that indicate the required state of the shift keys needed in order
to have the event described by f e treated as the keyboard focus change event.
-1 means that you don’t care. If you do care, use the same shift bits passed in the
Event structure as discussed in the Handling Input chapter in the SunView 1
Programmer's Guide, e.g., LEFTSHIFT.
win_get_f ocus_event () returns the values set by
win_set_focus_event().
void
win_get_focus_event(windowfd, fe, shifts)
int windowfd;
Firm_event *fe;
int *shifts;
*f e and *shift s are filled in with the current values.
Another ways to change the keyboard focus is to restore the caret. Restoring the
focus swallows the focus change event so that it never makes it to the applica¬
tion. These two routines parallel the focus setting routines described above.
void
win__set_swallow__event (windowfd, fe, shifts)
int windowfd;
Firm_event *fe;
int shifts;
Event Specification
Setting the Caret Event
Getting the Caret Event
Restoring the Caret
void
win_get_swallow_event(windowfd, fe, shifts)
int windowfd;
Firm_event *fe;
int ^shifts;
Revision A, of May 9, 1988
60 SunView 1 System Programmer’s Guide
This section discusses the concept of input synchronization in some detail. It’s
an important but subtle system mechanism. You should understand it fully
before changing the system’s default synchronization setting.
When running with input synchronization enabled, only one input event is being
consumed, or processed, at a time. This event is called the current event. Own¬
ership of the current event is bestowed by SunView to a single process; that pro¬
cess is said to have the current event lock. The lock belongs to a process, not a
window device and is used to prevent any process from receiving an input event
(via a read(2) system call) until the the lock has been released. This prevents
race conditions between processes. This lets, for example, a user pop a window
to the top and start typing to it before its image is drawn and have typing directed
to the correct window. Input synchronization allows the process that currently
has the lock to change its input mask and have the change recognized immedi¬
ately so that applications won’t miss events when they fall behind the user.
Input synchronization is not to be confused with the management of the input
focus. The input focus is that window which is supposed to get the next input
event and the input synchronization mechanism is used to determine when the
current input event processing is completed.
The current event lock is acquired upon completing a read of a window device in
which an input event was successfully read. For the duration of the lock, the
current event lock owner decides what to do based on the current event and does
it (or forks a process to do it). There is no notification to the input focus of input
pending until the current event lock is released. Thus, there is typically only one
process actively reading input at a time (except for rogue polling processes).
Releasing the Current Event When a process finishes with the current event, the current event lock is released
Lock via:
□ A read(2) of the next event. If the next event is for the window that is
doing the read then the lock is released and re-acquired immediately.
□ A select(2) for input. This is the common case.
□ An explicit win_release_event_lock () call (see below).
An explicit lock release call is appropriate for an application that knows that it no
longer needs to query the state of the virtual input device or change its input
mask and is about to do something moderately time consuming. Such an appli¬
cation can explicitly release the lock as soon as it recognizes that the event it has
just read is not going to change event distribution.
win_release_event_lock(windowfd)
int windowfd;
Current Event Lock Breaking The current event lock is broken by SunView when the process with it visits the
debugger or dies.
In addition, SunView explicitly breaks the current event lock if an application
takes too long to process the event. The time is measured in process virtual time,
not real time. This is a quiet lock breaking in that no message is displayed and
Revision A, of May 9,1988
7.4. Synchronization
Control
Chapter 7 — Workstations 61
J
no signal is sent to the offending process. The duration of the time limit can be
set, for the entire workstation, to a range of values:
□ 0 — Windows have rampant race conditions. There is poor performance on
high speed mouse tracking because the system can’t compress mouse motion
passed to applications.
□ non-zero (approximately 1-10 seconds) — Most synchronization problems
go away except when programs exceed the time limit. When SunView
detects a process that exceeds the time limit the process temporarily goes
into an unsynchronized mode until it catches up with the user.
□ large-infinite (greater than 10 seconds) — Synchronization problems don’t
arise. Unfortunately, the user is locked into just one program at a time
echoing/noticing input The key combination 1 Setun-I I (the I Setup 1 key is
the 1 Stop 1 key on Sun-2 and Sun-3 machines) explicitly breaks the lock.
Getting/Setting the Event Lock The default time limit is 2 cpu seconds. You can get the current event lock
Timeout timeout with a call to win_get_event_timeout ():
void
win_get_event_timeout(windowfd, tv)
int windowfd;
struct timeval *tv;
*tv is filed in with the current value.
You can set the current event lock timeout via a call to
win_set_event_timeout ():
void
win_set_event_timeout(windowfd, tv)
int windowfd;
struct timeval *tv;
*tv is used as the current value.
7.5. Kernel Tuning Options Some kernel tuning variable are settable using a debugger. However, you are
advised not to change these unless you absolutely have to. You can look at the
kernel with a debugger to see the default settings of these values, but your are
playing with fire.
□ int ws_vq_node_byt es is the number bytes to use for the input queue.
You might increase this number if you find your are getting “Window input
queue overflow!” and “Window input queue flushed!” messages. This needs
to be modified before starting SunView in order to have any affect.
□ int ws_fast_timeout is the number of hertz between polls of input
devices when in fast mode. SunView polls its input devices at two speeds.
The fast mode is the normal polling speed and the slow mode occurs when
no action has been detected in the input devices for
ws_fast_j)oll_duration hertz. This is all meant to save cpu cycles of
useless polling when the user is not doing anything. The system is con¬
stantly bouncing between slow and fast polling mode.
microsystems
Revision A, of May 9, 1988
62 SunView 1 System Programmer’s Guide
ws_f ast_t imeout should never be 0. Decreasing this number improves
interactive cursor tracking at the expense of increased system polling load.
□ int ws_s low_t imeout is the number of hertz between polls of input
devices when in slow mode. ws_slow_t imeout should never be 0.
Decreasing this number improves interactive cursor tracking at the expense
of increased system polling load.
o int ws_fast_poll_duration is discussed above. Increasing this
number improves interactive performance at the expense of increased system
polling load.
□ int ws_loc_s t i 11 is the number of hertz after which, if the locator has
been still, a LOC_STILL event is generated.
o struct timeval ws_lock_limit is the process virtual time limit
for a data or display lock. Increasing ws_lock_limit reduces the
number of
... lock broken after time limit exceeded ...
console messages at the expense of slower response to dealing with lock
hogs.
□ int ws_check_lock and struct timeval ws_check_time
The check for ws_lock_limit doesn’t start for ws_check_lock
amount of real time after the lock is set. This is done to avoid system over¬
head for normal short lock intervals. Increasing ws_check_lock reduces
system overhead on long lock holding situations at the expense of slower
response to dealing with lock hogs.
□ int win_disable_shared_locking is a flag that controls whether
or not the window driver will try to reduce the overhead of display locking
by using a shared memory mechanism. Even though there are no known
problems with the shared memory locking mechanism, this variable is avail¬
able as an escape hatch. If the window system leaves mouse cursor drop¬
pings, set this variable to 1. The default is 0. Setting this variable to 1 will
result in reduced graphics performance.
□ int winclistchar smax is the maximum number of characters from
the operating system’s “character buffer” pool that SunView is willing to
utilize. Upping this number can reduce “tossed” input situations. Turning
on wintossmsg (an int) will print a message if input has to be tossed,
winclistcharsmax should only be increased by half again as much as
its default.
□ int ws_set_f avor is a flag that controls whether or not the window
driver will try to boost the priority of the window process (and its children)
that has the current event lock. The default is 1. In very tight memory situa¬
tions this dramatically improves interactive performance.
Revision A, of May 9, 1988
Chapter 7 — Workstations 63
Changing the User Actions that The following is provided so that you can change the user actions for the various
Affect Input real time interrupt actions.
typedef struct ws_usr_async {
short
dont_touchl;
short
first_id;
/*
id of
the 1st event */
int
first_value;
/*
value
of the 1st event
*/
short
second_id;
/*
id of
the 2nd event */
int
second__value;
/*
value
of the 2nd event
*/
int
dont touch2;
} Ws_usr_async
Ws_usr_async ws_break_default = /* Event lock breaking */
{0, SHIFT_TOP, 1, TOP_FIRST + 'i', 1, 0};
Ws_usr_async ws_stop_default = /* Stop event */
{0, SHIFT_TOP, 1, SHIFT_TOP, 0, 0};
Ws_usr_async ws_flush_default = /* Input queue flushing */
{0, SHIFT_TOP, 1, TOP_FIRST + ', 1 , 0};
microsystems
Revision A, of May 9, 1988
Advanced Notifier Usage
Advanced Notifier Usage.
8.1. Overview.
Contents.
Viewpoint.
Further Information.
8.2. Notification.
Client Events.
Delivery Times.
Handler Registration.
The Event Handler.
SunView Usage.
Output Completed Events.
Exception Occurred Events.
Getting an Event Handler.
8.3. Interposition.
Registering an Interposer.
Invoking the Next Function.
Removing an Interposed Function
8.4. Posting.
Client Events.
Delivery Time Hint.
Actual Delivery Time
Posting with an Argument.
Storage Management. 78
SunView Usage. 79
Posting Destroy Events. 80
Delivery Time. 80
Immediate Delivery . 80
Safe Delivery. 80
8.5. Prioritization. 81
The Default Prioritizer... 81
Providing a Prioritizer. 81
Dispatching Events. 82
Getting the Prioritizer. 83
8.6. Notifier Control. 85
Starting. 85
Stopping. 85
Mass Destruction. 85
Scheduling. 86
Dispatching Clients. 86
Getting the Scheduler. 87
Client Removal . 87
8.7. Error Codes. 88
8.8. Restrictions on Asynchronous Calls into the Notifier. 90
8.9. Issues. 91
8.1. Overview
Contents
Viewpoint
Further Information
Advanced Notifier Usage
This chapter continues the description of the Notifier in The Notifier chapter of
the SunView 1 Programmer’s Guide.
This chapter presents areas which are not of general interest to the majority of
SunView application programmers. These include:
□ The registration of client, output and exception event handlers.
□ Querying for the current address of one of a client’s event handlers.
□ Interposition of any event handler.
□ Controlling the order in which a client receives events.
□ Control over the dispatching of events.
□ Controlling the order in which clients are notified.
□ A list of error codes.
□ Restrictions on calls into the Notifier.
□ A list of open issues surrounding the Notifier.
Although the Notifier falls under the umbrella of SunView, the Notifier can be
looked at as a library package that is usable separately from the rest of SunView.
The viewpoint of this chapter is one in which the Notifier stands alone from Sun¬
View. However, there are notes about SunView’s usage of the Notifier
throughout the chapter.
You must read the chapter titled The Notifier in the SunView 1 Programmer’s
Guide before you tackle this chapter; it has information and examples about the
Notifier and SunView’s usage of it. In addition, The Agent & Tiles chapter in
this manual has further information.
This split description of the Notifier may be a little awkward for advanced users
of the Notifier but is much less confusing for the majority of users. You should
refer to the index in the SunView 1 Programmer’s Guide first and then the index
in this book when using this material in a reference fashion.
microsystems
67
Revision A, of May 9,1988
68 Sun View 1 System Programmer’s Guide
8.2. Notification
This section presents the programming interface to the Notifier that clients use to
register event handlers and receive notifications.
Links to the SunView 1 Programmer*s
Guide.
Only those areas not covered in the Notifier chapter of the SunView 1
Programmer’s Guide are presented. In particular, input pending refers to the sec¬
tion in the other manual.
The two Notifier chapters are different in that the SunView 1 Programmer’s
Guide considers the Notifier in relation to SunView; thus, for example, in it
notifier events are SunView Input Events, so their type is Event *. In this
chapter, event is the more general type Notif y_event.
Client Events
This section describes how client events are handled by the Notifier. From the
Notifier’s point of view, client events are defined and generated by the client.
Client events are not interpreted by the Notifier in any way. The Notifier doesn’t
detect client events, it just detects UNIX-related events. The Notifier is responsi¬
ble for dispatching client events to the client’s event handler after the event has
been posted with the Notifier by application code (see the section entitled Post¬
ing below).
Delivery Times
The Notifier normally sends client event notifications when it is safe to do so.
This may involve some delay between when an event is posted and when it is
delivered. However, a client may ask to always be immediately notified of the
posting of a client event (see Posting, below).
Client Defined Signals
The immediate client event notification mechanism should be viewed as an
extension of the UNIX signaling mechanism in which events are client defined
signals. However, clients are strongly encouraged to only use safe client event
handlers.
Handler Registration
To register a client event handler call:
Notify_func
notify_set_event_func(client, event_func, when)
Notify_client client;
Notify_func event_func;
Notify_event_type when;
enum notify_event_type {
NOTIFY_SAFE=0,
NOTIFY IMMEDIATE=1,
);
typedef enum notify_event_type Notify_event_type;
when indicates whether the event handler will accept notifications only when it
is safe (NOTIFY_SAFE) or at less restrictive times (NOTIFY_IMMEDIATE). 16
16 For a rundown of the basics of registering event handlers see the section on Event Handling in the Notifier
chapter of the SunView 1 Programmer’s Guide.
®sun
Xr microsystems
Revision A, of May 9,1988
Chapter 8 — Advanced Notifier Usage 69
The Event Handler
SunView Usage
Output Completed Events
The calling sequence of a client event handler is:
Notify_value
event_func(client, event, arg, when)
Notify_client client;
Notify_event event;
Notify_arg arg;
Notify_event_type when;
typedef caddr_t Notify_arg;
in which client is the client that called not if y_set_event_f unc ().
event is passed through from notif y_post_event ( ) (see Posting,
below), arg is an additional argument whose type is dependent on the value of
event and is completely defined by the client, like event, when is the actual
situation in which event is being delivered (NOTIFY_SAFE or
NOTIF Y_IMMED I ATE ) and may be different from when_hint of
not if y_post_event (). The return value is one of NOTIFY_DONE or
NOTIFY_IGNORED.
You will almost certainly not need to directly register your own client event
handler when using SunView. Window objects do this for themselves when they
are created. However, note the following:
□ A window has a client event handler that you may want to interpose in front
of. See the section entitled Monitoring and Modifying Window Behavior in
the Notifier chapter in the SunView 1 Programmer’s Guide.
□ SunView client event handlers are normally registered with when equal to
NOTIFY_SAFE.
□ The Agent reads input events from a window’s file descriptor and posts them
to the client via the win_post_event ( ) call. See the section titled
Notifications From the Agent in The Agent & Tiles chapter.
Notifications for output completed notifications are similar to input pending
notifications, covered in the chapter on the Notifier in the SunView 1
Programmer’s Guide.
Notify_func
notify_set_output_func(client, output_func, fd)
Notify_client client;
Notify_func output_func;
int fd;
Notify_value
output_func(client, fd)
Notify_client client;
int fd;
&sun
\r microsystems
Revision A, of May 9, 1988
70 Sun View 1 System Programmer’s Guide
Exception Occurred Events Exception occurred notifications are similar to input pending notifications. The
only known devices that generate exceptions at this time are stream-based socket
connections when an out-of-band byte is available. Thus, a SIGURG signal
catcher is set up by the Notifier, much like SIGIO for asynchronous input.
Notify_func
notify_set_exception_func(client , exception_func, fd)
Notify_client client;
Notify_func exception_func;
int fd;
Notify_value
exception_func(client, fd)
Notify_client client;
int fd;
Getting an Event Handler Here is the list of routines that allow you to retrieve the value of a client’s event
handler. The arguments to each notif y_get__*__func () function parallel
the associated notif y_set_*_f unc () function described elsewhere except
for the absence of the event handler function pointer. Thus, we don’t describe
the arguments in detail here. Refer back to the associated
notif y_set_*_f unc () descriptions for details. 17
A return value of NOTIFY_FUNC_NULL indicates an error. If client is unk¬
nown then notif y_errno is set to NOTIFY_UNKNOWN_CLIENT. If no
event handler is registered for the specified event then notif y_errno is set to
NOTIFY_NO_CONDITION. Other values of notify__errno are possible,
depending on the event, e.g., NOTIFY_BAD_FD if an invalid file descriptor is
specified (see the associated notif y_set_*_f unc ()).
Here is a list of event handler retrieval routines:
Notify_func
notify__get_input_func (client, fd)
Notify_client client;
int fd;
Notify_func
notify_get_event_func(client , when)
Notify_client client;
Notify__event__type when;
Notify_func
notify_get_output_func(client, fd)
Notify_client client;
int fd;
Notify_func
17 It is recommended that you use the Notifier’s interposition mechanism instead of trying to do
interposition yourself using these notify_get_*_func () routines.
sun
microsystems
Revision A, of May 9, 1988
Chapter 8 — Advanced Notifier Usage 71
notify_get_exception_func(client, fd)
Notify_client client;
int fd;
Notify_func
notify_get_itimer_func(client, which)
Notify__client client;
int which;
Notify_func
not if y_get_signal__func (client, signal, mode)
Not if y__client client ;
int signal;
Notify_signal_mode mode;
Notify_func
notify_get_wait3_func(client, pid)
Notify_client client;
int pid;
Notify_func
notify_get_destroy_func(client)
Notify_client client;
microsystems
Revision A, of May 9,1988
72 Sun View 1 System Programmer’s Guide
8.3. Interposition
Registering an Interposer
NOTE
There are many reasons why an application might want to interpose a function in
the call path to a client’s event handler:
□ An application may want to use the fact that a client has received a particular
notification as a trigger for some application-specific processing.
□ An application may want to filter the notifications to a client, thus modifying
the client’s behavior.
□ An application may want to extend the functionality of a client by handling
notifications that the client is not programmed to handle.
The Notifier supports interposition by keeping track of how interposition func¬
tions are ordered for each type of event for each client. Here is a typical example
of interposition:
□ An application creates a client. The client has set up its own client event,
handler using notify_set_event_func ().
□ The application tells the Notifier that it wants to interpose its function in
front of the client’s event handler by calling
notify_interpose_event_func () (described below).
□ When the application’s interposed function is called, it tells the Notifier to
call the next function, i.e., the client’s function, via a call to
notify_next_event_func () (described below).
The following routines let you interpose your own function in front of a client’s
event handler. The arguments to each not if y_interpose_*_f unc ()
function parallel the associated not if y_set_*_func () function described
above. Thus, we don’t describe the arguments in detail here. Refer back to the
associated notify_set_*_func () descriptions for details.
The one exception to this rule is that the arguments to
not if y_interpose_itimer_f unc () are a subset of the arguments to
notify_set_itimer_func().
Notify_error
notify_interpose_input_func(client, input_func, fd)
Notify_client client;
Notify_func input_func;
int fd;
Notify_error
notify_interpose_event_func(client, event_func, when)
Notify_client client;
Notify_func event_func;
Notify_event_type when;
Notify_error
notify_interpose_output_func(client, output_func, fd)
Notify_client client;
Notify_func output_func;
int fd;
sun Revision A, of May 9, 1988
microsystems
Chapter 8 — Advanced Notifier Usage 73
Notify_error
notify_interpose_exception_func(client, exception_func, fd)
Notify_client client;
Notify_func exception_func;
int fd;
Notify_error
notif y_interpo se_i time r__f unc (client, itimer_func, which)
Not if y__client client ;
Notify__func itimer_func;
int which;
Notify__error
notify_interpose_signal_func(client,
signal,
Notify_client
Notify_func
int
Notif y__s igna l_mode
client;
signal_func;
signal;
mode ;
signal_func,
mode)
Notify_error
notify_interpose_wait3_func(client, wait3_func, pid)
Not if y__client client ;
Notify_func wait3_func;
int pid;
Notify_error
notify_interpose__destroy_func(client, destroy_func)
Notify__client client ;
Notify_func destroy_func;
The return values from these functions may be one of:
□ NOTIFY_OK — The interposition was successful.
□ NOTIFY__UNKNOWN_CLIENT — client is not known to the Notifier.
□ NOTIF Y__NO_COND ITI ON —nn There is no event handler of the type
specified.
□ NOTIFY_FUNC_LIMIT — The current implementation allows five levels
of interposition for every type of event handler, the original event handler
registered by the client plus five interposers. NOTIFY_FUNC_JLIMIT indi¬
cates that this limit has been exceeded.
If the return value is something other than NOTIFY_OK then not if y_errno
contains the error code.
Invoking the Next Function Here is the list of routines that you call from your interposed function in order to
invoke the next function in the interposition sequence. The arguments and return
value of each not if y_next_*_f unc () function are the same as the argu¬
ments passed to the your interposer function. Thus, we don’t describe the argu¬
ments in detail here. Refer back to the associated event handler descriptions for
details.
microsystems
Revision A, of May 9, 1988
74 Sun View 1 System Programmer’s Guide
Removing an Interposed
Function
Notify_value
notify_next_input_func(client, fd)
Not if y__client client ;
int fd;
Notify__value
notify_next_event_func(client, event, arg, when)
Notify__client client;
Notify_event *event;
Notify_arg arg;
Not if y_event__type when ;
Notify__value
notify_next__output__func (client, fd)
Notify_client client;
int fd;
Notify__value
notify_next_exception_func(client, fd)
Notify_client client;
int fd;
Notify__value
notify_next_itimer_func(client, which)
Notif y__client client ;
int which;
Notify__value
notify_next_signal_func(client, signal, mode)
Not if y__client client;
int signal;
Notify_signal_mode mode;
Notify_value
not if y__next__wait3_func (client, pid, status, rusage)
Notif y__client client ;
union wait status;
struct rusage rusage;
int pid;
Notify__value
notify_next_destroy_func(client, status)
Notify_client client;
Dest roy__status status ;
Here is the list of routines that allow you to remove the interposer function that
you installed using a notif y^interpose_*_f unc () call. The arguments
to each notif y_remove_*_func () function is exactly the same as the asso¬
ciated notif y_set_*__f unc () function described above. Thus, we don’t
describe the arguments in detail here.
Nr microsystems
Revision A, of May 9,1988
Chapter 8 — Advanced Notifier Usage 75
NOTE The one exception to this rule is that the arguments to
not if y_remove__i timer _f unc () are a subset of the arguments to
notif y_set_itimer_func ().
Notify__error
notify_remove_input_func (client, input_func, fd)
Notify_client client;
Notify_func input__func;
int fd;
Notify_error
notify_remove_event_func(client, event_func, when)
Notify_client client;
Notify_func event_func;
Notify_event__type when;
Notify_error
notify_remove_output_func(client, output_func, fd)
Not if y__client client ;
Notify__func output_func;
int fd;
Notify__error
not if y__remove__exception_f unc (client, except ion_f unc, fd)
Notify_client client;
Notify_func exception_func;
int fd;
Notify_error
not if y_remove_itimer__f unc (client, itimer___func, which)
Notify_client client;
Notify_func itimer_func;
int which;
Notify_error
notify_remove_signal__func(client, signal_func, signal, mode)
Notify_client client;
Notify_func signal_func;
int signal;
Notify__signal_mode mode;
Notify___error
notify_remove_wait3_func(client, wait3_func, pid)
Notify_client client;
Notify__func wait 3_f unc;
int pid;
Notify_error
notify_remove_destroy_func(client, destroy_func)
Notify_client client;
Notify_func destroy_func;
Revision A, of May 9, 1988
76 SunView 1 System Programmer’s Guide
If the return value is something other than NOTIFY_OK then not if y_errno
contains the error code. The error codes are the same as those associated with
notify_interpose_*_func () calls.
Asun
microsystems
Revision A, of May 9, 1988
Chapter 8 — Advanced Notifier Usage 77
8.4. Posting
This section describes how to post client events and destroy events with the
Notifier.
Client Events
A client event may be posted with the Notifier at any time. The poster of a client
event may suggest to the Notifier when to deliver the event, but this is only a
hint. The Notifier will see to it that it is delivered at an appropriate time (more
on this below). The call to post a client event is:
typedef char * Notify_event;
Notify_error
notify_j?ost_event(client, event, when_hint)
Notify_client client;
Notify_event event;
Notify_event_type when_hint;
The client handle from notify set event func () is passed to
notif y_j?ost_event (). event is defined and interpreted solely by the
client. A return code of NOTIFY_OK indicates that the notification has been
posted. Other values indicate an error condition. NOTIFY UNKNOWN CLIENT
indicates that client is unknown to the Notifier. NOTIFY NO CONDITION
indicates that client has no client event handler registered with the Notifier.
Delivery Time Hint
Usually it is during the call to notif y_post_event () that the client event
handler is called. Sometimes, however, the notification is queued up for later
delivery. The Notifier chooses between these two possibilities by noting which
kinds of client event handlers client has registered, whether it is safe and what
the value of when_hint is. Here are the cases broken down by which kinds of
client event handlers client has registered:
□ Immediate only — Whether when_hint is NOTIFY SAFE or
NOTIFY_IMMEDIATE the event is delivered immediately.
□ Safe only — Whether when_hint is NOTIFY_SAFE or
NOTIFY_IMMEDIATE the event is delivered when it is safe.
□ Both safe and immediate — A client may have both an immediate client
event handler as well as a safe client event handler. If when hint is
NOTIFY_SAFE then the notification is delivered to the safe client event
handler when it is safe. If when_hint is NOTIFY IMMEDIATE then the
notification is delivered to the immediate client event handler right away. If
the immediate client event handler returns NOTIFY IGNORED then the
same notification will be delivered to the safe client event handler when it is
safe.
Actual Delivery Time
For client events, other than knowing which event handler to call, the main func¬
tion of the Notifier is to know when to make the call. The Notifier defines when
it is safe to make a client notification. If it is not safe, then the event is queued
up for later delivery. Here are the conventions:
□ A client that has registered an immediate client event handler is sent a
notification as soon as it is received. The client has complete responsibility
microsystems
Revision A, of May 9, 1988
78 Sun View 1 System Programmer’s Guide
Posting with an Argument
Storage Management
for handling the event safely. It is rarely safe to do much of anything when
an event is received asynchronously. Usually, just setting a flag that indi¬
cates that the event has been received is about the safest thing that can be
done.
o A client that has registered a safe client event handler will have a
notification queued up for later delivery when the notification was posted
during an asynchronous signal notification. Immediate delivery is not safe
because your process, just before receiving the signal, may have been exe¬
cuting code at any arbitrary place.
□ A client that has registered a safe client event handler will have a
notification queued up for later delivery if the client’s safe client event
handler hasn’t returned from processing a previous event. This convention
is mainly to prevent the cycle: Notifier notifies A, who notifies B, who
notifies A. A could have had its data structures tom up when it notified B
and was not in a state to be reentered.
Implied in these conventions is that a safe client event handler is called immedi¬
ately from other UNIX event handlers. For example:
□ A client’s input pending event handler is called by the Notifier.
□ Two characters are read by the client’s input pending event handler.
□ The first character is given to the Notifier to deliver to the client’s safe event
handler.
a The Notifier immediately delivers the character to the client event handler.
□ Returning back to the input pending event handler, the second character is
sent. This character is also delivered immediately.
SunView posts a fixed field structure with each event. Sometimes additional data
must be passed with an event, for instance when the scrollbar posts an event to
its owner to do a scroll. The scrollbars’ handle is passed as an argument along
with the event, notif y_post_event_and_arg () provides this argument
passing mechanism (see below).
When posting a client event there is the possibility of delivery being delayed. In
the case of SunView, the event being posted is a pointer to a structure. The
Notifier avoids an invalid (dangling) pointer reference by copying the event if
delivery is delayed. It calls routines the client supplies to copy the event infor¬
mation and later to free up the storage the copy uses,
notif y_post_event_and_arg () provides this storage management
mechanism.
microsystems
Revision A, of May 9, 1988
Chapter 8 — Advanced Notifier Usage 79
SunView Usage
Notify_error
not if y_jpost__event_and_arg (client, event, when__hint, arg,
copy_func, release_func)
Notify_client client;
Notify__event event;
Notify_event__type when_hint ;
Notify_arg arg;
Notify_copy copy_func;
Notify__release release_func;
typedef caddr__t Notify_arg;
typedef Notify_arg (*Notify_copy)();
#define NOTIFY_COPY_NULL ((Notify_copy)0)
typedef void (*Notify_release)();
#define NOTIFY__RELEASE___NULL ( (Notify_release) 0)
copy__f unc () is called to copy arg (and optionally event) when event
and arg needed to be queued for later delivery, release_func () is called to
release the storage allocated during the copy call when event and arg were no
longer needed by the Notifier.
Any of arg, copy_func () or release_func () may be null. If
copy_f unc is not NOTIFY__COPY_NULL and arg is NULL then
copy_func () is called anyway. This allows event the opportunity to be
copied because copy_f unc () takes a pointer to event. The pointed to event
may be replaced as a side affect of the copy call. The same applies to a non-
NOTIFY_RELEASE_NULL release function with a NULL arg argument.
The copy () and release () routines are client-dependent so you must write
them yourself. Their calling sequences follow:
Notify_arg
copy_func(client,
Notify_client
Notify_arg
Notify_event
arg, event_ptr)
client;
arg;
*event_j?tr;
void
release__func (client, arg, event)
Notify_client client;
Notify_arg arg;
Notify__event event;
There are Agent calls to post an event to a tile that provide a layer over the post¬
ing calls described here (see win_post_event () in the chapter entitled The
Agent & Tiles).
Revision A, of May 9,1988
80 SunView 1 System Programmer’s Guide
Posting Destroy Events
Delivery Time
Immediate Delivery
Safe Delivery
When a destroy notification is set, the Notifier also sets up a synchronous signal
condition for SIGTERM that will generate a DESTROY_PROCESS_DEATH des¬
troy notification. Otherwise, a destroy function will not be called automatically
by the Notifier. One or two (depending on whether the client can veto your
notification) explicit calls to notif y_post_destroy () need be made.
Notify_error
notify_post_destroy(client, status, when)
Notify_client client;
Destroy_status status;
Notify_event_type when;
NOTIFY_INVAL is returned if status or when is not defined. After notifying
a client to destroy itself, all references to client are purged from the Notifier.
Unlike a client event notification, the Notifier doesn’t try to detect when it is safe
to post a destroy notification. Thus, a destroy notification can come at any time.
It is up to the good judgement of a caller of notify_post_destroy () or
notif y_die () (described in the section titled Notifier Control ) to make the
call at a time that a client is not likely to be in the middle of accessing its data
structures.
If status is DESTROY_CHECKING and when is NOTIFY_IMMEDIATE then
notify post destroy () may return NOTIFY_DESTROY_VETOED if the
client doesn’t want to go away.
Often you want to tell a client to go away at a safe time. This implies that
delivery of the destroy event will be delayed, in which case the return value of
not if y__post_destroy () can’t be NOTIFY_DESTROY_VETOED because
the client hasn’t been asked yet. To get around this problem the Notifier will
flush the destroy event of a checking/destroy pair of events if the checking phase
is vetoed. Thus, a common idiom is:
—
(void) notify_post_destroy(client, DESTROY_CHECKING,
NOTIFY_SAFE);
(void) notify_post_destroy(client, DESTROY_CLEANUP,
NOTIFY_SAFE);
•._ J
microsystems
Revision A, of May 9,1988
Chapter 8 — Advanced Notifier Usage 81
8.5. Prioritization
The Default Prioritizer
Providing a Prioritizer
The order in which a particular client’s conditions are notified may be controlled
by providing a prioritizer operation. 18
The default prioritizer makes its notifications in this order (any asynchronous or
immediate notifications have already been sent):
□ Interval timer notifications (ITIMER_REAL and then ITIMER_VIRTUAL).
□ Child process control notifications.
□ Synchronous signal notifications by ascending signal numbers.
□ Exception file descriptor activity notifications by ascending fd numbers.
□ Handle client events by order in which received.
□ Output file descriptor activity notifications by ascending fd numbers.
□ Input file descriptor activity notifications by ascending fd numbers.
This section describes how a client can provide its own prioritizer.
Notify_func
notify_set_prioritizer_func(client, prioritizer_func)
Notify_client client;
Notify_func prioritizer_func;
notif y_set_prioritizer_func () takes an opaque client handle and the
function to call before any notifications are sent to client. The previous func¬
tion that would have been called is returned. If this function was never defined
then the default prioritization function is returned. If the
prior it izer_func () argument is NOTIFY_FUNC_NULL then no client
prioritization is done for client and the default prioritizer is used.
The calling sequence of a prioritizer function is:
Notify_value
prioritizer_func(client, nfd, ibits_ptr, obits_ptr,
ebits_ptr, nsig, sigbits_ptr, auto_sigbits_ptr,
event_count_ptr, events, args)
Notify_client client;
fd_set *ibits_ptr, *obits_ptr, *ebits_ptr;
int nfd, nsig, *sigbits__ptr,
* auto_sigbit s_pt r, *event_count_pt r;
*events;
Notify_event
Notify_arg
'"args;
♦define SIG_BIT(sig)
(1 « ((sig)-1))
in which client from notify set prioritizer_func () are passed to
prioritizer_f unc (). In addition, all the notifications that the Notifier is
planning on sending to client are described in the other parameters. This data
reflects only data that client has expressed interest in by asking for
18 It is anticipated that this facility will be rarely used by clients and that a client will rely on the ordering
provided by the default prioritizer.
microsystems
Revision A, of May 9,1988
82 SunView 1 System Programmer’s Guide
Dispatching Events
notification of these conditions.
nf d describes the maximum number of valid bits in the f d_set structures 19
pointed to by ibitsj>tr, obits_ptr, and ebits_ptr. ibits_ptr
points to a bit mask of those file descriptors with input pending for client;
similarly obit s_ptr points to a bit mask of file descriptors with output com¬
pleted, and ebits_ptr points to a bit mask of file descriptors on which an
exception occurred, nsig describes the maximum number of valid bits in the
arrays pointed to by sigbits_ptr and auto_sigbits_j?tr.
si gbit s_pt r is a bit mask of signals received for which client has a condi¬
tion registered; the SIG_BIT macro can be used to access the correct bit.
auto_sigbit s_j?tr is a bit mask of signals received that the Notifier is
managing on behalf of client. event_count is the number of events in the
array events, events is an array of pending client events and args is the
parallel array of event arguments.
The return value is one of NOTIFY_DONE or NOTIFY_IGNORED. These have
their normal meanings:
□ NOTIFY_DONE — All of the conditions had notifications sent for them.
This implies that no further notifications should be sent to client this time
around the notification loop. Unsent notifications are preserved for con¬
sideration the next time around the notification loop.
□ NOT IFY_IGN0RED — A notification was not sent for one or more of the
conditions, i.e., some notifications may have been sent, but not all. This
implies that another prioritizer should try to send any remaining notifications
to client.
From within a prioritization routine, the following functions are called to cause
the specified notifications to be sent:
Notify_error
notify_event(client, event, arg)
Notify_client client;
Notify_event event;
Notify_arg arg;
Notify_error
notify_input(client, fd)
Notify_client client;
int fd;
Notify_error
notify_output(client, fd)
Notify_client client;
int fd;
Notify_error
19 With the increase past 32 of the maximum number of file descriptors under SunOS Release 4.0, the masks
of FD bits are no longer ,ints but a special structure, defined in <sys /type s. h>.
sun
microsystems
Revision A, of May 9,1988
Chapter 8 — Advanced Notifier Usage 83
notify_exception(client, fd)
Notify_client client;
int
fd;
Notify_error
notify__itimer (client, which)
Notify_client client;
int
which;
Notify_error
notify_signal(client, signal)
Notif y__client client ;
int
signal;
Notify_error
notify_wait3(client)
Notify_client client;
The Notifier won’t send any notifications that it wasn’t planning on sending any¬
way, so one can’t use these calls to drive clients programmatically. A return
value ofNOTIFY_OK indicates that client was sent the notification. A return
value of NOTIFY_UNKNOWN_CLIENT indicates that client is not recognized
by the Notifier and no notification was sent. A return value of
NOTIFY__NO_CONDITION indicates that client does not have the requested
notification pending and no notification was sent.
A client may chose to replace the default prioritizer. Alternatively, a client’s
prioritizer may call the default prioritizer after sending only a few notifications.
Any notifications not explicitly sent by a client prioritizer will be sent by the
default prioritizer (when called), in their normal turn. Once notified, a client will
not receive a duplicate notification for the same event.
Signals indicated by bits in sigbits_ptr should call notify_signal ().
Signals in auto_sigbits_ptr need special treatment:
□ SIGALRM means that notif y_itimer () should be called with a which
Of ITIMER_REAL.
□ SIGVTALRM means that notif y_itimer () should be called with a
which of ITIMER__VIRTUAL.
□ SIGCHLD means that notif y_wait3 () should be called.
Asynchronous signal notifications, destroy notifications and client event
notifications that were delivered right when they were posted do not pass through
the prioritizer.
Getting the Prioritizer
notif y_get_prioritizer_func () returns the current prioritizer of a
client.
Notify_func
notify_get_jprioritizer_func (client)
Notify_client client;
notif y_get_prioritizer_func () takes an opaque client handle. The
Revision A, of May 9, 1988
84 SunView 1 System Programmer’s Guide
function that will be called before any notifications are sent to client is
returned. If this function was never defined for client then a default function
is returned. A return value of NOTIFY_FUNC_NULL indicates an error. If
client is unknown then notif y_errno is set to
NOTIFY UNKNOWN CLIENT.
microsystems
Revision A, of May 9, 1988
Chapter 8 — Advanced Notifier Usage 85
8.6. Notifier Control
Starting
Stopping
Mass Destruction
The following are the Notifier wide (vs single condition) operations.
Here is the routine for starting the notification loop of the Notifier:
Notify_error
notify_start()
This is the main control loop. It is usually called from the main routine of your
program after all the clients in your program have registered their event handlers
with the Notifier . 20 The return values are:
□ NOTlFY_OK — Terminated normally by notify_stop () (see below).
□ NOTIFY_NO_COND ITI ON — There are no conditions registered with the
Notifier.
o NOTIFY_INVAL — Tried to call notif y_start () before returned from
original call, i.e., this call is not reentrant
□ NOTIFY_BADF — One of the file descriptors in one of the conditions is not
valid.
An application may want to break the Notifier out its main loop after the Notifier
finishes sending any pending notifications.
Notify_error
notify_stop()
This causes notify_start () to return. The return values are NOTIFY_OK
(will terminate notif y_start () ) and NOTIFY_NOT_STARTED
(notify_start () not entered).
The following routine causes the all client destruction functions to be called
immediately with status:
Notify_error
notify_die(status)
Destroy_status status;
This causes the all client destruction functions to be called immediately with
status as the reason. The return values are NOTlFY_OK or
NOTlFY_DESTROY_VETOED; the latter indicates that someone called
notif y_veto_destroy () and status was DESTROY_CHECKING. It is
then the responsibility of the caller of notif y_die () to exit the process, if so
desired. See the discussion on not if y_post_destroy () for more informa¬
tion.
20 SunView programs usually call window_main_loop() instead of notify_start ().
microsystems
Revision A, of May 9,1988
86 SunView 1 System Programmer’s Guide
Scheduling
There is the mechanism for controlling the order in which clients are notified.
(Controlling the order in which a particular client’s notifications are sent to it is
done by that client’s prioritizer operation; see the Prioritization section earlier.)
Notify_func
notify set_scheduler_func(scheduler_func)
Notify_func scheduler_func;
notify set scheduler f unc () allows you to arrange the order in which
clients are called. (Individual clients can control the order in which their event
handlers are called by setting up prioritizers.)
notify set scheduler_func () takes a function to call to do the
scheduling of clients. The previous function that would have been called is
returned. This returned function will (almost always) be important to store and
call later because it is most likely the default scheduler.
Replacement of the default scheduler will be done most often by a client that
needs to make sure that other clients don’t take too much time servicing all of
their notifications. For example, if doing “real-time” cursor tracking in a user
process, the tracking client wants to schedule itself ahead of other clients when¬
ever there is input pending on the mouse.
The calling sequence of a scheduler function is:
Notify_value
scheduler_func(n, clients)
int n;
Notify_client *clients;
in which a list of n clients, all of which are slated to receive some notification
this time around, are passed into scheduler_f unc (). The scheduler scans
clients and makes calls to notif y_client () (see below). Clients so
notified should have their slots in clients set to NOTIFY_CLIENT_NULL.
The return value from scheduler_f unc () is one of:
□ NOTIFY DONE — All of the clients had a chance to send notifications.
This implies that no further clients should be scheduled this time around the
notification loop. Unsent notifications are preserved for consideration the
next time around the notification loop.
□ NOTIFY IGNORED — One or more clients were scheduled, i.e., some
clients may have been scheduled, but not all. This implies that another
scheduler should try to schedule any clients in client s that are not
NOTIFY_CLIENT_NULL.
Dispatching Clients
The following routine is called from scheduler routines to cause all the pending
notifications for client to be sent:
Notify_error
notify_client(client)
Notify_client client;
The return value is one of NOTIFY_OK (client notified) or
NOTIFY NO CONDITION (no conditions for client, perhaps
notify client () was already called with this client handle) or
V microsystems
Revision A, of May 9,1988
Chapter 8 — Advanced Notifier Usage 87
NOTIFY_UNKNOWN__CLIENT (unknown client).
Getting the Scheduler
The following routine returns the function that will be called to do client schedul¬
ing:
Notify__func
notify_get_scheduler__func ()
This function is always defined to at least be the default scheduler.
Client Removal
A client can remove itself from the control of the Notifier with
notify__remove ():
Notify_error
notify_remove(client)
Notif y__client client ;
notif y_remove () is a utility to allow easy removal of a client from the
Notifier’s control. All references to client are purged from the Notifier. This
routine is almost always called by the client itself. The return values are
NOTIFYJDK (success) and NOTIF Y_UNKN 0 WN_C LIE NT (unknown client).
Revision A, of May 9, 1988
88 SunView 1 System Programmer’s Guide
8.7. Error Codes This section describes the basic error handling scheme used by the Notifier and
lists the meaning of each of the possible error codes. Every call to the Notifier
returns a value that indicates success or failure. On an error condition,
notif y_errno describes the failure, not if y_errno is set by the Notifier
much like errno is set by UNIX system calls, i.e., not if y_errno is set only
when an error is detected during a call to the Notifier and is not reset to
NOTIFY_OK on a successful call to the Notifier.
enum notify_error {
... /* Listed below */
};
typedef enum notify_error Notify_error;
extern Notify_error notify_errno;
Here is a complete list of error codes:
□ NOT IF Y_OK — The call was completed successfully.
□ NOTIFY_UNKNOWN_CLIENT — The client argument is not known by
the Notifier. A notif y_set_*_func type call need be done in order for
the Notifier to recognize a client.
□ NOTIFY_NO_CONDITION — A call was made to access the state of a con¬
dition but the condition is not set with the Notifier for the given client. This
can arise when a notify_get_*_func () type call was done before the
equivalent notif y_set_*_f unc () call was done. Also, the Notifier
automatically clears some conditions after they have occurred, e.g., when an
interval timer expires.
□ NOTIFY_BAD_ITIMER — The which argument to an interval timer rou¬
tine was not valid.
□ NOTIFY_BAD_SIGNAL — The signal argument to an signal routine
was out of range.
□ NOTIFY_NOT_STARTED — A call to notify_stop () was made but
the Notifier was never started.
□ NOTIFY_DESTROY_VETOED — A client refused to be destroyed during a
call to notify_die () or notif y_post_destroy () when status
was DESTROY__CHECKING.
□ NOTIFY_INTERNAL_ERROR — This error code indicates some internal
inconsistency in the Notifier itself has been detected.
□ NOTIFY_SRCH — The pid argument to a child process control routine
was not valid.
□ NOTIFY_BADF — The f d argument to an input or output routine was not
valid.
□ NOTIFY_NOMEM — The Notifier dynamically allocates memory from the
heap. This error code is generated if the allocator could not get any more
memory.
microsystems
Revision A, of May 9, 1988
Chapter 8 — Advanced Notifier Usage 89
□ NOTIFY_lNVAL — Some argument to a call to the Notifier contained an
invalid argument.
□ NOTIFY_FUNC_LIMlT — An attempt to set an interposer function has
encountered the limit of the number of interposers allowed for a single con¬
dition.
The routine not if y_j>error () acts just as the library call perror(3).
notify_perror(str)
char *str;
notify_perror () prints the string str, followed by a colon and followed
by a string that describes notif y_errno to stderr.
Revision A, of May 9,1988
90 SunView 1 System Programmer’s Guide
8.8. Restrictions on
Asynchronous Calls
into the Notifier
The Notifier takes precautions to protect its data against corruption during calls
into it while it is calling out to an asynchronous/immediate event handler. The
Notifier may issue an asynchronous notification for an asynchronous signal con¬
dition, an immediate client event condition or a destroy condition. Most calls
from event handlers back into the Notifier are permitted, but there are some res¬
trictions:
□ Some calls are not permitted. In particular, they are:
notify_start()
notify_client()
□ Only a certain number of calls into the Notifier are permitted. This restric¬
tion is due to how the Notifier handles memory management in a safe way
during asynchronous processing. As a guideline, do not do more than five
calls of the notif y_set_*_f unc (),
notify_interpose_*_func() or notify post *() variety dur¬
ing an asynchronous notification.
The Notifier is not prepared to handle calls into it from signal catching rou¬
tines that a client has set up with signal(3) or sigvec(2).
Nr microsystems
Revision A, of May 9,1988
Chapter 8 — Advanced Notifier Usage 91
8.9. Issues Here are some issues surrounding the Notifier:
□ The layer over the UNIX signal mechanism is not complete. Signal blocking
(sigblock(2)) can still safely be done in the flow of control of a client to
protect critical portions of code as long as the previous signal mask is
restored before returning to the Notifier. Signal pausing (sigpause(2)) is
essentially done by the Notifier. Signal masking (sigmask(2)) can be
accomplished via multiple notif y_set_signal_f unc ( ) calls. Set¬
ting up a process signal stack (sigstack(2)) can still be done. Setting the
signal catcher mask and on-signal-stack flag (sigvec(2)) could be done by
reaching around the Notifier but is not supported.
□ Not all process resources are multiplexed (e.g., rlimit(2), set jmp(2),
umask(2), setquota(2), and setpriority(2)), only ones that have to
do with flow of control multiplexing. Thus, some level of cooperation and
understanding need exist between packages in the single process.
□ One can make a case for intercepting close(2) and dup(2) calls so that the
Notifier is not waiting on invalid or incorrect file descriptors if a client for¬
gets to remove its conditions from the Notifier before making these calls.
□ One can make a case for intercepting signal(3) and sigvec(2) calls so
that the Notifier doesn’t get confused by programs that fail to use the
Notifier to manage its signals.
□ One can make a case for intercepting set itimer(2) calls so that the
Notifier doesn’t get confused by programs that fail to use the Notifier to
manage interval timers.
□ One can make a case for intercepting ioctl(2) calls so that the Notifier
doesn’t get fouled up by programs that use FIONBIO and FIOASYNC
instead of the equivalent f cnt 1(2) calls.
□ One can make a case for intercepting readv(2) and wr ite(2) just like
read(2) and select(2) so that a program doesn’t tie up the process.
□ The Notifier is not a lightweight process mechanism that maintains a stack
per thread of control. However, if such a mechanism becomes available then
the Notifier will still be valuable for its support of notification-based clients.
□ Client events are disjoint from UNIX events. This is done to give complete
freedom to clients as to how events are defined. One could imagine certain
clients wanting to unify client and UNIX events. This could be done with a
layer of software on top of the Notifier. A client could define events as
pointers to structures that contain event codes and event specific arguments.
The event codes would include the equivalents of UNIX event notifications.
The event specific arguments would contain, for example, the file descriptor
of an input-pending notification. When an input-pending notification from
the the Notifier was sent to a client, the client would turn around and post the
equivalent client event notification.
□ One could imagine extending the Notifier to provide a record and replay
mechanism that would drive an application. However, this is not supported
by the current interface.
Revision A, of May 9,1988
,
■
The Selection Service and Library
The Selection Service and Library. 95
9.1. Introduction. 95
9.2. Basic Concepts. 96
9.3. Fast Overview. 96
The Selection Service vs. the Selection Library. 97
9.4. Selection Service Protocol: an Example. 97
Secondary Selection Between Two Windows. 97
Notes on the Above Example. 101
9.5. Topics in Selection Processing. 101
Reporting Function-Key Transitions. 101
Sending Requests to Selection Holders. 102
Long Request Replies. 104
Acquiring and Releasing Selections. 104
Callback Procedures: Function-Key Notifications. 104
Responding to Selection Requests. 105
Callback Procedures: Replying to Requests. 106
9.6. Debugging and Administrative Facilities. 109
9.7. Other Suggestions . 109
If You Die. 109
9.8. Reference Section. HO
Required Header Files. 110
Enumerated Types. 110
Other Data Definitions. 110
Procedure Declarations. 112
9.9. Common Request Attributes. 121
9.10. Two Program Examples. 125
get selection Code. 125
selndemo . 128
Large Selections. 128
The Selection Service and Library
9.1.
Introduction
The Selection Service package provides for flexible communication among win¬
dow applications. It is concerned with aspects of the selection[s] the user has
made, and with the status of the user interface which may affect those selections.
It has 3 distinct aspects:
1. A server process maintains a clearinghouse of information about the selec¬
tion, and the function keys which may affect how a selection is made. This
process responds to RPC requests for information from clients. Normally,
the RPC accesses will be done only by library routines described below;
therefore details of that access do not appear in this manual.
2. A library of client routines is provided to communicate with the clearing¬
house process and with each other. These routines allow a client to acquire a
selection, or yield it to another application, to determine the current holder
of a selection, and send or receive requests concerning a selection’s contents
and attributes.
3. A minimal set of requests is defined for communicating between applica¬
tions which have some interest in the selection. This set is deliberately
separated from the transport mechanism mentioned under (2) above, and the
form of a request is carefully separated from its content. This allows appli¬
cations to treat the definition of what can be said about the selection as
open-ended; anything consenting applications agree to can be passed
through the Selection Service.
This chapter is primarily concerned with the transport library, and how to use
that protocol to accomplish representative application tasks. The (current) set of
generic requests is also presented, and used in illustrations.
The next sections is a fast overview of how the Selection Service works, and a
walk-through of the complex protocol followed when selections are transferred
between client. This is followed by several discursive sections devoted to partic¬
ular aspects of using the Selection Service, such as reporting function-key transi¬
tions, sending requests, acquiring and releasing selections, replying to requests,
and debugging selection applications. Throughout these sections, some pro¬
cedures and data types are mentioned or described. Full documentation for all of
these may be found in the reference section which follows. Finally there are two
example programs which show how to use the Selection Service for simple
queries (get_selection) and how a real client of the selection service works
(selndemo).
Xr microsystems
95
Revision A, of May 9,1988
96 SunView 1 System Programmer’s Guide
The remainder of the chapter comprises reference material: descriptions of the
public data and procedures of the selection library, a list of the defined common
attributes, and the complete source of a program to retrieve the contents of a
selection and print it on stdout.
9.2. Basic Concepts When a user makes a selection, it is some application program which interprets
the mouse and function-key events and resolves them into a particular selection.
The Selection Service is involved only as the processing of function-keys and
selections spans application windows. Application programs interact with the
package in proportion to the sophistication of their requirements. This section is
intended to present the information necessary for any use of the Selection Ser¬
vice, and to indicate what further information in the document pertains to various
uses of the package.
The selection library deals with four objects under the general term “ selection .”
Most familiar is the Primary selection, which is normally indicated on-screen by
inverting (“highlighting”) its contents. Selections made while a function key is
held down (usually indicated with an underscore) are Secondary selections. The
selection library treats the Shelf 21 (the global buffer which is loaded by Cut 22
and Copy operations, and which may be retrieved by a Paste operation) as a
third kind of selection. Finally, the insertion point, or Caret, is also treated as a
selection, even though it has no contents. These are the four ranks the selection
library deals with: Caret, Primary, Secondary, and Shelf.
Every selection has a holder, this is a piece of code within a process which is
responsible for operating on the selection and responding to other applications’
requests about it. A selection holder is a client of the selection library. Typi¬
cally, a selection client is something like a subwindow; there may be several
selection clients within a single process.
Because the selection library uses RPC as well as the SunView input system, it
relies on the SunView Notifier to dispatch events; thus any application using the
selection library must be built on the notifier system.
9.3. Fast Overview The simplest use of the Selection Service is to inquire about a selection held by
some other application. Programs which never make a selection will not use the
facilities described in the rest of this section. Much of the material remaining
before the beginning of reference section is likewise irrelevant to these programs:
the sections on Acquiring and Releasing Selections and Callback Procedures
pertain only to clients which make selections.
A program which will actually make selections should be a full-fledged client of
the selection library. Such an application calls seln_create () during the
client’s initialization routines; if successful, this returns an opaque client handle
which is then passed back in subsequent calls to selection library procedures.
21 The shelf is called the Clipboard in user-oriented documentation such as the SunView 1 Beginner's
Guide , and in the text subwindow menu.
22 Prior to SunOS Release 4.0, the terms Delete t Put t and Get were used instead of the “industry-standard”
Cut, Copy, and Paste.
\r microsystems
Revision A, of May 9,1988
Chapter 9 — The Selection Service and Library 97
The Selection Service vs. the
Selection Library
9.4. Selection Service
Protocol: an Example
Secondary Selection Between
Two Windows
Two arguments to this create-procedure specify client callback procedures which
may be called to perform processing required by external events. These are the
function_j?roc () and the reply_proc () described below.
Note the difference here between the Selection Service program, and the selec¬
tion library. The former is a separate program, selection_svc(l), the latter
is the code in a SunView application which knows how to talk to the Selection
Service and its other clients. After a client is successfully created, it may call
library routines to:
□ inquire of the Selection Service how to get in touch with the holder of a par¬
ticular rank of selection,
□ send a request to such a holder (e.g. to find out the contents of a selection),
□ inform the Selection Service of any change in the state of the function keys
□ acquire a selection, and later,
□ release a selection it has acquired.
The client must be prepared to deal with:
□ reports from the Selection Service of function key transitions it may be
interested in (these are handled by its function_proc ( ))
□ requests from other clients about selections it holds (these are handled by its
reply_proc ()).
Finally, when the client is finished, it calls seln_destroy () to clean up its
selection library resources.
It’s important to remember that the Selection Service is an external process
which client programs talk to to find out about the selections held by other
clients. To clarify the conceptual model, here’s an outline of the communication
which takes place when a user makes a secondary selection between two win¬
dows.
Try the sequence out yourself while you read the description; The following
description assumes that you have a standard set-up (focus follows cursor, adjust¬
ing selections does not make them pending-delete, left mouse button is select,
middle is extend/adjust, etc.). If you have trouble performing the operation, the
SunView 1 Beginner’s Guide has more to say on selections.
1. Move the cursor into one text subwindow (call it “window A”). Note how
the border of the subwindow darkens.
2. Click LEFT in window A to select a character. Window A sets the caret and
highlights the primary selection you have just made.
3. Hold down the I Paste I key (usually [ L8) ).
4. Move the cursor into another text subwindow (call it “window B”).
5. Click LEFT and MIDDLE in window B to select some text. Note how it
underlines the selection to indicate that it is a secondary selection.
The Selection Service vs. the
Selection Library
9.4. Selection Service
Protocol: an Example
Secondary Selection Between
Two Windows
Revision A, of May 9,1988
98 SunView 1 System Programmer’s Guide
6. Release the 1 Paste 1 key. Note how the secondary selection from window B
appears at the caret in window A.
Here’s what happens internally when this sequence of user actions takes place.
Assume window A and B have registered as clients of the Selection Service
using seln_create (). The initial state is no function keys down, and no one
holds any of the selections.
Table 9-1 Selection Service Scenario
Revision A, of May 9,1988
Chapter 9 — The Selection Service and Library 99
Table 9-1 Selection Service Scenario — Continued
Client A Selection Service
Client B Notes
User presses left mouse button (but has not released yet).
seln_acquire( 3
UNSPECIFIED)
Check state of function keys;
since I Paste I is Down, note caller
as secondary holder; return
secondary.
Provide feedback to indicate
secondary selection at indicated
point If user has held down the
1 Control 1 kev. secondary selec-
tion may be pending-delete.
User releases left mouse button.
no action required
User presses middle mouse button (but has not released yet).
provide feedback for adjustment
of secondary selection
User releases middle mouse button.
no action required
User releases [Paste] key.
Note that this key-up leaves all
function keys up. Figure out
which of the four selection hold¬
ers to notify (the primary selec¬
tion holder, A).
seln_report_event(B,
up-event)
B’s call to
seln_report_event()
gets notification in return; B
calls seln_f igure-
_response (), which says
IGNORE
#sun
\r microsystems
Revision A, of May 9,1988
100 SunView 1 System Programmer’s Guide
Table 9-1 Selection Service Scenario — Continued
Notes
Client B
Selection Service
Client A
Window A’s
function_proc () is called
(it was registered with the
Selection Service in
seln_create () to handle
reported function key transi¬
tions). The
function_jproc () in turn
calls
seln_figure_response(),
which tells it to request the con¬
tents of the secondary selection
from the secondary selection
holder.
So function_j?roc () calls
seln_init_request () to
set up a request to
a) get the contents of the secon¬
dary selection,
b) commit any pending-delete,
and yield secondary;
It then calls
seln_request () to send
this request to B.
The request arrives as an RPC
call to B’s request-proc ()
(likewise registered with the
Selection Service in
seln_create (), but the
reply proc handles requests
about selections). B provides
response to each attribute in the
request; in response to the
request to Yield(secondary), it
calls seln done (
SELN SECONDARY)
Note there is no holder of the
secondary selection.
Do pending delete if necessary:
remove selection; cache con¬
tents; call seln_acquire (
SELN SHELF)
Note caller as holder of the Shelf.
Return from rpc call.
Revision A, of May 9,1988
Chapter 9 — The Selection Service and Library 101
Table 9-1
Selection Service Scenario — Continued
Client A
Consume response, inserting
contents; if primary selection
were pending delete, then
would delete primary (supersed
ing B as holder of Shelf if so).
Selection Service
Client B
Notes
Notes on the Above Example
1. To be absolutely correct, clients should determine whether they want the
Caret when they get a KBD_USE event, and acquire it immediately if so.
Code to do this would look something like
Client A
Selection Service
Client B
Notes
User moves cursor into window A.
Get KBD USE event.
Call seln_get_-
function_state()
seln_acquire(
SELN_CARET)
Return state of function keys
(all up).
But this would involve waking up a client every time the cursor crossed its win¬
dow; further, the kernel sends spurious KBD_USEs on window-crossings when a
function key is down; Hence most clients postpone acquiring the Caret until they
know they have input. For most clients, input is usually signalled by a key going
down (either a function-key or a regular ASCII-key).
2. Some window types acquire the Caret and primary selection at this point, so
they simply call seln_acquire (client handle,
SELN_UNSPECIFIED) when a key goes down.
3. This “Point Down” describes what most windows implement, as opposed to
the first theoretical exchange. The issue is whether clients call
seln_inquire (client, SELN_UNSPECIFIED) , and then acquire the
appropriate selection, or whether they should simply call
seln_acquire (client, SELN_UNSPECIFIED).
When an application makes a selection, its rank depends on the state of the func¬
tion keys. (A secondary selection is one made while a function key is held
down.) The application which is affected by a function-key transition may not be
the one whose window received that transition. Consequently, this system
requires that the service be informed of transitions on those function keys that
affect the rank of a selection; the service then provides that state information to
9.5. Topics in Selection
Processing
Reporting Function-Key
Transitions
microsystems
Revision A, of May 9, 1988
102 Sun View 1 System Programmer’s Guide
any application which inquires.
The keys which affect the rank of a selection are [ Copy) , 1 Paste I . [Cut I . and
fFindl (ordinarily these are keys (L0, (HD, IL1Q1 , and CGD, respectively). If an
application program does not include these events in its input mask, then they
will fall through to the root window, and be reported by it. But if the application
is reading these events for any reason, then it should also report the event to the
service. seln_report_event () is the most convenient procedure for this
purpose; seln_inf orm () does the work at a lower level.
When the service is told a function key has gone up, it will cause calls to the
function_proc callback procedures of the holders of each selection. For the client
that reports the key-up, this will happen during the call to
seln_report_event; for other holders, it can happen any time control
returns to the client’s notifier code. The required processing is detailed under
Callback Procedures below. Programs which never called seln_create ()
can call seln_report_event () without incurring any extra processing —
they have no function_proc to call.)
Two procedures are provided so that clients may interrogate state of the functions
keys as stored by the service: seln_get_function_state () takes a
Seln_f unction and returns TRUE or FALSE as the service believes that
function key is down or not. seln_f unctions_state () takes a pointer to a
Seln_functions_state buffer (a bit array which will be all 0 if the service
believes all function keys are currently up).
Sending Requests to Selection
Holders
Inside the selection library, a request is a buffer (a Seln_request structure);
the following declarations are relevant to the processing that is done with such a
buffer:
typedef struct {
Seln_result (*consume)();
char
} Seln_requester;
typedef struct {
Seln_replier_data
Seln_requester
char
Seln_rank
Seln_result
unsigned
char
} Seln_request;
*context;
*replier;
requester;
*addressee;
rank;
status;
buf_size;
data[SELN_BUFSIZE];
Clients of the Selection Service inquire of it who holds a particular rank of selec¬
tion using seln_inquire (); they then talk directly to each other through
request buffers. A client loads an attribute value list of its requests about the
rank of selection into these buffers. Requests include things like “What are the
contents of the selection?”, “What line does the selection start on?”, “Please give
up the selection (I need to highlight)!”, and so forth.
»sun
xr microsystems
Revision A, of May 9, 1988
Chapter 9 — The Selection Service and Library 103
/* VARARGS */
Seln_request *
seln_ask(holder, <attributes>, ... 0)
Seln_holder ^holder;
Attr_union attribute;
/* VARARGS */
void
seln_init_request(buffer, holder, <attributes>, ... 0)
Seln_request *buffer;
Seln_holder ^holder;
char ^attributes;
/* VARARGS */
Seln_result
seln_query(holder,
Seln_holder
Seln_result
char
Attr union
reader, context, <attributes>,
*holder;
(^reader) () ;
^context;
attribute;
0 )
Seln__result
reader(buffer)
Seln_request *buffer;
The selection library routines pass request buffers from clients to the particular
client who holds that rank of selection. That client returns its reply in one or
more similar buffers. The library is responsible for maintaining the dialogue, but
does not have any particular understanding of the requests or their responses.
seln_query () (or seln_ask (), for clients unwilling to handle replies of
more than one buffer) is used to construct a request and send it to the holder of a
selection.
There is a lower-level procedure, seln_request () which is used to send a
pre-constructed buffer containing a request, and an initializer procedure,
seln_init_request () which can be used to initialize such a buffer.
The data portion of the request buffer is an attribute-value list, copied from the
<attributes> . . . arguments in a call to seln_query ( ) or
seln_ask () . A similar list is returned in the reply, typically with real values
replacing placeholders provided by the requester. (It may take several buffers to
hold the whole reply list; this case is discussed below.)
The request mechanism is quite general: an attribute-value pair in the request
may indicate some action the holder of the selection is requested to perform —
even a program to be executed may be passed, as long as the requester and the
holder agree on the interpretation.
The header file <suntool/selection__attributes . h> defines a base set
of request attributes; a copy is printed near the end of this chapter. The most
common request attribute is S E LN_REQ_CONTENT S_AS C11, which requests
microsystems
Revision A, of May 9, 1988
104 Sun View 1 System Programmer’s Guide
the holder of the selection to return its contents as an ASCII string.
Long Request Replies
If the reply to a request is very long (more than about 2000 bytes), more than one
buffer will be used to return the response. In this case, seln_ask () simply
returns a pointer to the first buffer and discards the rest.
NOTE
This means that that the attribute value list in the first buffer may not be properly
terminated (but it probably will be).
seln_query () should be used if long replies are to be handled gracefully.
Rather than returning a buffer, it repeatedly calls a client procedure to handle
each buffer in turn. The client passes a pointer to the procedure to be called in
the reader argument of the call to seln_query () (that address appears in
the consume element of the Seln_requester struct.) Such procedures
typically need some context information to be saved across their invocations; this
is provided for in the context element of the Seln_requester structure.
This is a 32-bit datum provided for the convenience of the reader procedure; it
may be filled in with literal data or a pointer to some persistent storage; the value
will be available in each call to reader, and may be modified at will.
Selection holders are responsible for processing and responding to the attributes
of a request in the order they appear in the request buffer. Selection holders may
not recognize all the attributes in a request; there is a standard response for this
case: In place of the unrecognized attribute (and its value, if any), the replier
inserts the attribute SELN_REQ_UNRECOGNI ZED, followed by the original
(unrecognized) attribute. This allows heterogeneous applications to negotiate the
level at which they will communicate.
A straightforward example of request processing (including code to handle a long
reply) is the get_selection program, which appears at the end this chapter.
Acquiring and Releasing
Selections
Applications in which a selection can be made must be able to tell the service
they now hold the selection, and they must be able to release a selection, either
on their own initiative, or because another application has asked to acquire it.
Seln_acquire is used both to request a current holder of the selection to
yield, and then to inform the service that the caller now holds that selection.
seln_yield() is used to yield the selection on the caller’s initiative. A
request to yield because another application is becoming the holder is handled
like other requests; this is discussed under Callback Procedures below.
Callback Procedures:
Function-Key Notifications
When you register a client with the Selection Service using seln_create (),
you must supply a function_proc() and a reply_proc(). The former is called by
the Selection Service to report function-key transitions (which may have
occurred in other windows) to the client; the latter is called by the Selection Ser¬
vice when this client holds one of the selections and other clients have requests
about it.
The selection library calls the client’ s function_proc() when the Selection Service
is informed of a function-key transition which leaves all function keys up. This
may happen inside the client’s call to seln_report_event (), if the report¬
ing client holds a selection; otherwise the call will arrive through the RPC
V microsystems
Revision A, of May 9, 1988
Chapter 9 — The Selection Service and Library 105
mechanism to the function_proc ().
The relevant declarations are:
typedef enum {
SELN_IGNORE, SELN_REQUEST, SELN_FIND,
SELN_SHELVE, SELN_DELETE
} Seln_response;
typedef struct {
Seln_f unction function;
Seln_rank addressee_rank;
Seln_holder caret;
Seln_holder primary;
Seln_holder secondary;
Seln_holder shelf;
} Seln_function_buffer;
Seln_response
seln_figure_response(buffer, holder)
Seln_function_buffer *buffer;
Seln_holder **holder;
void
function_proc(client_data, function)
char *client_data;
Seln_function_buffer *function;
f unction_j?roc () will be called with a copy of the 32 bits of client data ori¬
ginally given as the third argument to seln_create (), and a pointer to a
Seln_f unct ion_buf f er. The buffer indicates what function is being
invoked, which selection the called program is expected to be handling, and what
the Selection Service knows about the holders of all four selection ranks (one of
whom is the called program). A client will only be called once, even if it holds
more than one selection. (In that case, the buffer’s addressee_rank will
contain the first rank the client holds.)
Responding to Selection
Requests
The holders of the selections are responsible for coordinating any data transfer
and selection-relinquishing among themselves. The procedure
seln_f igure_response () is provided to assist in this task. It takes a
pointer to a function buffer such as the second argument to a function proc
callback, and a pointer to a pointer to a Seln_holder. It returns an indication
of the action which this client should take according to the standard interface. It
also changes the addressee_rank element of that buffer to be the rank which
is affected (the destination of a transfer, the item to be deleted, etc.), and if
interaction with another holder is required, it stores a pointer to the appropriate
Seln_holder element in the buffer into the location addressed by the second
argument. Here are the details for each return value:
SELN_IGNORE
No action is required of this client. Another client may make a request concern¬
ing the selection(s) this client holds.
V microsystems
Revision A, of May 9, 1988
106 SunView 1 System Programmer’s Guide
SELN_REQUEST This client is expected to request the contents of another selection and insert
them in the location indicated by buf f er—>addressee_rank. The holder
of the selection that should be retrieved is identified by *holder. If *holder
points to buf f er—>secondary, the request should include
SELN_REQ_YIELD; if it points to buf f er—>primary or
buf f er—>secondary, the request should include
SELN_REQ_COMMIT_PENDING_DELETE.
Example: the called program holds the Caret and Primary selection; the I Paste I
key went up, and there is no Secondary selection. The return value will be
SELN_REQUEST, buf fer—>addressee_rank will be SELN_CARET and
*holder will be the address of buf f er->shelf . The client should request
the contents of the shelf from that holder.
SELN_FIND This client should do a Find (if it can). Buf f er—>addressee_rank will be
SELN_CARET; if *holder is not NULL, the target of the search is the indicated
selection. If *holder points to buf f er->secondary, the request should
include SELN_REQ_YIELD.
SELN_SHELVE This client should acquire the shelf from *holder (if that is not NULL), and
make the current contents of the primary selection (which it holds) be the con¬
tents of the shelf.
SELN_DELETE This client should delete the contents of the secondary selection if it exists, or
else the primary selection, storing those contents on the shelf.
Buf f er—>addressee_rank indicates the selection to be deleted; *holder
indicates the current holder of the shelf, who should be asked to yield.
Seln_secondary_exists and seln_secondary_made are predicates
which may be of use to an application which is not using
seln_f igure_response (). Each takes a Seln_function_buf fer
and returns TRUE or FALSE. When the user has made a secondary selection and
then cancelled it, seln_secondary_made will yield TRUE while
seln_secondary_exists will yield FALSE. This indicates the function-
key action should be ignored.
Callback Procedures: The client’s reply_proc() callback procedure is called when another application
Replying to Requests makes a request concerning a selection held by this client. It is invoked once for
each attribute in the request, plus once for a terminating attribute supplied by the
selection library. The relevant declarations are:
microsystems
Revision A, of May 9, 1988
Chapter 9 — The Selection Service and Library 107
typedef struct {
char
Seln_rank
char
char
char
} Seln_replier
*client_data;
rank;
*context;
* * reque s t_pointe r;
**response_pointer;
data;
Seln_result
reply_j?roc(item, context, length)
caddr_t item;
Seln_replier__data *context;
int length;
reply_proc () will be called with each of the attributes of the request in turn,
item is the attribute to be responded to; context points to data which may be
needed to compute the response, and length is the number of bytes remaining
in the buffer for the response. reply_proc () should write any appropriate
response/value for the given attribute into the buffer indicated in
context->response_pointer, and return.
The fields of *context contain, in order:
□ the 32 bits of private client data passed as the last argument to
seln_create (), returned for the client’s convenience;
□ the rank of the selection this request is concerned with;
n a holder for 32 more bits of context for the replier’s convenience (this will
typically hold a pointer to data which allows a client to maintain state while
generating a multi-buffer response);
□ a pointer to a pointer into the request buffer, just after the current item (so
that the replier may read the value of this item if relevant). This pointer
should not be modified by reply_proc.
□ a pointer to a pointer into the response buffer, where the value / response (if
any) for this item should be stored. This pointer should be updated to point
past the end of the response stored. (Note that items and responses should
always be multiples of full-words; thus, this pointer should be left at an
address which is 0 mod 4.)
After storing the response to one item, reply_proc should return
SELN_SUCCESS and await the next call. When all attributes in a request have
been responded to, reply_proc will be called one more time with item ==
SELN_REQ_END_REQUEST, to give it a chance to clean up any internal state
associated with the request.
Two attributes which are quite likely to be encountered in the processing of a
request due to a function-key event, SELN_REQ_C0MMIT_PENDING_DELETE
and SELN_REQ_YIELD, are concerned more with the proper handling of secon¬
dary selections (rather than the needs of the requesting application), so they are
discussed here.
Revision A, of May 9, 1988
108 SunView 1 System Programmer’s Guide
SELN_REQ_COMMIT_PENDING_DELETE indicates that a secondary selection
which was made in pending-delete mode should now be deleted. If the recipient
does not hold the secondary selection, or the secondary selection is not in
pending-delete mode, the replier should ignore the request, i.e., simply return
SELN_SUCCESS and await the next call. SELN_REQ_YIELD, with an argu¬
ment of SELN_SECONDARY, means the secondary selection should be
deselected, if it still exists.
Complications on this basic model will now be addressed in order of increasing
complexity.
If the request concerns a selection the application does not currently hold,
reply__proc should return SELN_DIDNT_HAVE immediately; it will not be
called further for that request.
If the request contains an item the client isn’t prepared to deal with,
reply_proc should return SELN_UNRECOGNIZED immediately; the selec¬
tion library will take care of manipulating the response buffer to have the stan¬
dard unrecognized-format, and call back to reply_proc with the next item in
the list.
Finally, a response to a request may be larger than the space remaining in the
buffer — or larger than several buffers, for that matter. This situation will never
arise on items whose response is a single word — the selection library ensures
there is room for at least one 4-byte response in the buffer before calling
reply_proc.
If a response is too big for the current buffer, the replier should store as much as
fits in length bytes, save sufficient information to pick up where it left off in
some persistent location, store the address of that information in
context—>context, and return SELN_CONTINUED. Note that the replier’s
context information should not be local to reply_proc, since that procedure
will exit and be called again before the information is needed.
The selection library will ship the filled buffer to the requester, and prepare a new
one for the continuation of the response. It will then call reply_proc again,
with the same item and context, and length indicating the space available in
the new buffer. reply_proc () should be able to determine from
co ntext-> context that it has already started this response, and where to
continue from. It continues by storing as much of the remainder of the response
as fits into the buffer, updating context—>response_pointer (and its
own context information), and again returning SELN_CONTINUED if the
response is not completed. When the end of the response has been stored, includ¬
ing any terminator if one is required, the private context information may be
freed, and reply_proc should return SELN_SUCCESS.
The next call to reply_proc will be to respond to the next item in the request
if there is one, or else to SELN_REQ_END REQUEST.
Revision A, of May 9,1988
Chapter 9 — The Selection Service and Library 109
9.6. Debugging and
Administrative
Facilities
9.7. Other Suggestions
If You Die
A number of aids to debugging have been included in the system for applications
which use the Selection Service. In addition to providing information on how to
access holders of selections and maintaining the state of the user-interface keys,
the service will respond to requests to display traces of these requests, and to
dump its internal state on an output stream. Seln_debug is used to turn service
tracing on or off; seln_dump instructs the service to dump all or part of its
state on stderr.
A number of library procedures provide formatted dumps of Selection Service
structs and enumerated types. These can be found below as seln_dump_*.
In debugging an application which uses the Selection Service, it may be con¬
venient to use a separate version of the service whose state is affected only by the
application under test. This is done by starting the service with the -d flag; that
is, by entering /usr/bin/selection_svc -d & to a shell. The resulting
service will use a different RPC program number from the standard version, but
be otherwise identical. The two versions of the service may be running at the
same time, each responding to its own clients. A client may elect (via
seln_use_test_service ()) to talk to the test service. Thus, it is easy to
arrange to have an application under development talking to its own service,
while running under a debugger which is talking to a standard service — this
keeps the debugger, editors, etc. from interfering with the state maintained by the
test service.
The Selection Service depends heavily on remote procedure calls, using Sun’s
RPC library. It is always possible that the called program has terminated or is
not responding for some other reason; this is often detected by a timeout. The
standard timeout at this writing is 10 seconds; this is a compromise between
allowing for legitimate delays on loaded systems, and minimizing lockups when
the called program really won’t respond. The delay may be adjusted by a call to
seln_use_timeout.
Always call seln_f igure_response () to determine what to do with a
request
Use seln_report_event () instead of seln_inform () to report events
you aren’t interested in. Note that the canvas subwindow by default does not
report SunView function-key transitions; it relies on the events falling through to
the frame or root window, which does report the transitions.
If you expect to I Paste I the selection, you must acquire the Caret beforehand.
If your application dies, if it holds the shelf then you should save its contents by
writing them to a file and calling seln_hold_f ile (). You should also yield
the primary and secondary selections.
m sun
w microsystems
Revision A, of May 9, 1988
110 Sun View 1 System Programmer’s Guide
9.8. Reference Section
Required Header Files
Enumerated Types
Other Data Definitions
The reference material which follows presents first the header files and the public
data definitions they contain; then it lists each public procedure in the selection
library (in alphabetical order) with its formal parameter declarations, return
value, and a brief description of its effect.
#include <sunwindow/attr.h>
♦include <suntool/selection_svc.h>
♦include <suntool/selection attributes.h>
typedef enum {
SELN_FAILED, SELN_SUCCESS, /* basic uses */
SELN_NON_EXIST, SELN__DIDNT_HAVE, /* special cases */
S E LN_WRONG_RANK, SELN_CONTINUED,
S E LN_CANCE L, SELN_UNRECOGNIZED
} Seln__result ;
typedef enum {
SELN_UNKNOWN, SELN_CARET, SELNJPRIMARY,
SELN_SECONDARY, SELN_SHELF, SELN_UNSPECIFIED
} Seln_rank;
typedef enum {
SELN_FN__ERROR,
S E LN__FN_S T OP , S E LN_FN_AG A IN,
SELNJFN_PROPS, S E LN_FN_UND 0,
S E LN_FN__F RONT, SELN_FN_PUT,
SELN__FN_OPEN, S E LN__FN_GE T,
SELN__FN_F IND, SELN_FN_DELETE
} Seln_function;
typedef enum {
SELN_NONE, SELN_EXISTS, SELN__FILE
} Seln_state;
typedef enum {
SELN_IGNORE, S E LN_REQUE ST, SELN_FIND,
SELN__S HELVE, SELN__DELETE
} Seln_response;
typedef char *Seln_client;
typedef struct {
Seln_rank rank;
Seln_state state;
Seln_access access;
} Seln holder;
Seln holder
microsystems
Revision A, of May 9, 1988
Chapter 9 — The Selection Service and Library 111
typedef struct {
Seln__holder
Seln_holder
Seln__holder
Seln__holder
} Seln holders all
caret;
primary;
secondary
shelf;
typedef struct {
Seln_f unction
Seln_rank
Seln_holder
Seln_holder
Seln_holder
Seln holder
function;
addressee_rank;
caret;
primary;
secondary;
shelf;
}
Seln function buffer;
typedef struct
char
Seln__rank
char
char
char
*client_data;
rank;
^context;
**request_jpointer;
**response_pointer;
} Seln_replier_data;
typedef struct {
Seln_result (^consume)();
char ^context;
} Seln__requester;
♦define SELN__BUFSIZE
(1500 - sizeof(Seln_replier_data *)
- sizeof(Seln_requester)
- sizeof(char *)
- sizeof (Seln__rank)
- sizeof (Seln__result)
- sizeof(unsigned))
typedef struct {
Seln_replier_data
Seln_requester
char
Seln_rank
Seln_result
unsigned
char
} Seln_request;
*replier;
requester;
^addressee;
rank;
status;
buf_size;
data[SELN BUFSIZE];
\
\
\
\
\
\
microsystems
Revision A, of May 9, 1988
112 Sun View 1 System Programmer’s Guide
Procedure Declarations
Seln_rank
seln_acquire(client, asked)
Seln_client client;
Seln rank asked;
client is the opaque handle returned from seln_create (); the client uses
this call to become the new holder of the selection of rank asked, asked
should be one of SELN_CARET, SELN_PRIMARY, SELN_SECONDARY,
orSELN_SHELF, SELNJJNSPECIFIED. If successful, the rank actually
acquired is returned.
If asked is SELN_UNSPECIFIED, the client indicates it wants whichever of
the primary or secondary selections is appropriate given the current state of the
function keys; the one acquired can be determined from the return value.
/* VARARGS */
Seln_request *
seln_ask(holder, <attributes>, ... 0)
Seln_holder *holder;
Attr_union attribute;
seln_ask () looks and acts very much like seln_query (); the only differ¬
ence is that it does not use a callback proc, and so cannot handle replies that
require more than a single buffer. If it receives such a long reply, it returns the
first buffer, and discards all that follow. The return value is a pointer to a static
buffer; in case of error, this will be a valid pointer to a null buffer
(buffer— >status = SELN_FAILED). seln_ask() is provided as a
slightly simpler interface for applications that refuse to process long replies.
void
seln_clear_functions()
The Selection Service is told to forget about any function keys it thinks are
down, resetting its state to all-up. If it knows of a current secondary selection,
the service will tell its holder to yield.
Seln_client
seln_create(function_proc, reply_proc, client_data)
void (*function_proc) ();
void (*reply_proc) ();
caddr_t client_data);
The selection library is initialized for this client. If this is the first client in its
process, an RPC socket is established and the notifier set to recognize incoming
calls. Client data is a 32-bit opaque client value which the Selection Service
will pass back in callback procs, as described above. The first two arguments are
addresses of client procedures which will be called from the selection library
when client processing is required. These occasions are:
Revision A, of May 9,1988
Chapter 9 — The Selection Service and Library 113
□ when the service sees a function-key transition which may interest this
client, and
□ when another process wishes to make a request concerning the selection this
client holds,
Details of these procedures are described under Callback Procs, above.
/* VARARGS */
Seln_result
seln_debug(<attributes> ... 0)
Seln_attribute attribute;
A debugging routine which requests the service to turn tracing on or off for
specified calls. Each attribute identifies a particular call; its value should be 1 if
that call is to be traced, 0 if tracing is to be stopped. The attributes are listed with
other request-attributes in the first appendix. Tracing is initially off for all calls.
When tracing is on, the Selection Service process prints a message on its
stderr (typically the console) when it enters and leaves the indicated routine.
void
seln_destroy(client)
Seln_client client;
A client created by seln_create is destroyed: any selection it may hold is
released and various pieces of data associated with the selection mechanism are
freed. If this is the last client in this process using the Selection Service the RPC
socket is closed and its notification removed.
Seln_result
seln_done(client, rank)
Seln_client client;
Seln_rank rank;
Client indicates it is no longer the holder of the selection of the indicated rank.
The only cause of failure is absence of the Selection Service. It is not necessary
for a client to call this procedure when it has been asked by another client to
yield a selection; the service will be completely updated by the acquiring client.
void
seln_dump_function_buffer(stream, ptr)
FILE *stream;
Seln_function_buffer *ptr;
A debugging routine which prints a formatted display of a
Seln_f unct ion_buf f er struct on the indicated stream.
Revision A, of May 9,1988
114 Sun View 1 System Programmer’s Guide
void
seln_dump__function_key (stream, ptr)
FILE
^stream;
Seln_function *pt r;
A debugging routine which prints a formatted display of a
Seln_f unction_key transition on the indicated stream.
void
seln_dump_holder(stream, ptr)
FILE *stream;
Seln_holder *ptr;
A debugging routine which prints a formatted display of a Seln_holder struct
on the indicated stream.
void
seln_dump_rank (stream, ptr)
FILE ^stream;
Seln__rank *ptr;
A debugging routine which prints a formatted display of a Selnjrank value on
the indicated stream.
void
seln_dump__response (stream, ptr)
FILE ^stream;
Seln_response *ptr;
A debugging routine which prints a formatted display of a Seln_response
value on the indicated stream.
void
seln_dump_result (stream, ptr)
FILE ^stream;
Seln__result *ptr;
A debugging routine which prints a formatted display of a Seln__result value
on the indicated stream.
void
seln_dump_service(rank)
Seln_rank rank;
A debugging routine which requests the service to print a formatted display of its
internal state on its standard error stream. Rank determines which selection
holder is to be dumped; if it is SELN_UNSPECIFIED, all four are printed. In
any case, the dump concludes with the state of the function keys and the set of
Revision A, of May 9, 1988
Chapter 9 — The Selection Service and Library 115
open file descriptors in the service.
void
seln_dump_state(stream, ptr)
FILE
Seln state
^stream;
*ptr ;
A debugging routine which prints a formatted display of a Seln_state value
on the indicated stream.
Seln_response
seln__figure_response (buffer, holder)
Seln_function_buffer ^buffer;
Selnjiolder **holder;
A procedure to determine the correct response according to the standard user
interface when seln_inf orm () returns *buf f er, or the client’s
function_proc is called with it. The field addressee_rank will be modified
to indicate the selection which should be affected by this client; holder will be
set to point to the element of *buf f er which should be contacted in the ensuing
action, and the return value indicates what that action should be.
Seln_result
seln_functions_state(buffer)
Seln_functions__state *buffer;
The service is requested to dump the state it is maintaining for the function keys
into the bit array addressed by buff er. At present, the only commitment made
to representation in the buffer is that some bit will be on (== 1) for each function
key which is currently down. Thus this call can be used to determine whether
any function keys are down, but not which. SELNSUCCESS is returned unless
the service could not be contacted.
int
seln_get__function_state (which)
Seln_f unction which;
A predicate which returns TRUE when the service’s state shows the function key
indicated by which is down and FALSE otherwise.
Seln_result
seln_hold__file (rank, path)
Seln_rank rank;
char *path;
The Selection Service is requested to act as the holder of the specified rank,
whose ASCII contents have been written to the file indicated by path. This
allows a selection to persist longer than the application which made it can
Revision A, of May 9,1988
116 SunView 1 System Programmer’s Guide
maintain it Most commonly, this will be done by a process which holds the
shelf when it is about to terminate.
int
seln_holder_same_client(holder, client_data)
Seln_holder *holder;
char *client_data;
A predicate which returns TRUE if the holder referred to by holder is the same
selection client as the one which provided client_data as its last argument to
seln create.
int
seln_holder_same_j?rocess (holder)
Seln holder *holder;
A predicate which returns TRUE if the holder is a selection client in the same
process as the caller. (This procedure is used to short-circuit RPC calls with
direct calls in the same address space.)
Seln_function_buffer
seln_inform(client,
Seln_client
Seln_function
int
which, down)
client;
which;
down;
This is the low-level, policy-independent procedure for informing the Selection
Service that a function key has changed state. Most clients will prefer to use the
higher-level procedure seln_report_event (), which handles much of the
standard interpretation required.
Client is the client handle returned from seln_create (); it may be 0 if the
client guarantees it will never need to respond to the function transition. Which
is an element of the Seln_f unction enum defined in
<suntool/selection_svc. h>; down is a boolean which is TRUE if the
key went down.
On an up-event which leaves all keys up, the service informs the holders of all
selections of the transition, and what other parties are affected. If the caller of
seln_inf orm () is one of these holders, its notification is returned as the
value of the function; other notifications go out as a call on the client’s
function_proc callback procedure (described above under Callback Procedures).
Only one notification is sent to any single client. If the caller does not hold any
selection, or if the transition was not an up which left all function keys up, the
return value will be a null Seln_f unction_buf f er; buffer. rank will
be SELN UNKNOWN.
XT microsystems
Revision A, of May 9, 1988
Chapter 9 — The Selection Service and Library 117
/* VARARGS */
void
seln_init_request(buffer, holder, <attributes>, ... 0)
Seln_request
Seln_holder
char
*buffer;
*holder;
*attributes;
This procedure is used to initialize a buffer before calling seln_request . (It
is also called internally by seln_ask and seln_query.) It takes a pointer to
a request buffer, a pointer to a struct referring to the selection holder to which the
request is to be addressed, and a list of attributes which constitute the request to
be sent. The attributes are copied into buf f er—>data, and the corresponding
size is stored into buf f er—>buf_size. Both elements of
requester_data are zeroed; if the caller wants to handle long requests, a
consumer-proc and context pointers must be entered in these elements after
seln_init_request returns.
Seln_holder
seln_inquire(rank)
Seln_rank rank;
A Seln_holder struct is returned, containing information which enables the
holder of the indicated selection to be contacted. If the rank argument is
SELN_UNSPECIFIED, the Selection Service will return access information for
either the primary or secondary selection holder, as warranted by the state of the
function keys it knows about; the rank element in the returned struct will indi¬
cate which is being returned.
This procedure may be called without having called seln_create () first. If
no contact between this process and the service has been established yet, it will
be set up, and then the call will proceed as usual. In this case, return of a null
holder struct may indicate inaccessibility of the server.
Seln_holders_all
seln_inquire_all()
A Seln_holders_all struct is returned from the Selection Service; it con¬
sists ofaSeln holder struct for each of the four ranks.
Revision A, of May 9,1988
118 SunView 1 System Programmer’s Guide
Seln__result
reader(buffer)
Seln_request *buffer;
/* VARARGS */
Seln_result
seln_query(holder,
Seln_holder
Seln_result
char
Attr union
reader, context, <attributes>, ... 0)
^holder;
(^reader) () ;
^context;
attribute;
A request is transmitted to the selection holder indicated by the holder argu¬
ment. Consume and context are used to interpret the response, and are
described in the next paragraph. The remainder of the arguments to
seln_query constitute an attribute value list which is the request. (The last
argument should be a 0 to terminate the list.)
The procedure pointed to by consume will be called repeatedly with a pointer
to each buffer of the reply. The value of the context argument will be avail¬
able in buf f er—>requester_data. context for each buffer. This item is
not used by the selection library; it is provided for the convenience of the client.
When the reply has been completely processed (or when the consume proc
returns something other than SELN_SUCCESS), seln_query returns.
void
seln_report_event(client, event)
Seln_client__node ^client;
struct inputevent *event;
#define SELN_REPORT (event) seln_report__event (0, event)
This is a high-level procedure for informing the selection service of a function
key transition which may affect the selection. It incorporates some of the policy
of the standard user interface, and provides a more convenient interface to
seln_inform().
Client is the client handle returned from seln_create; it may be 0 if the
client guarantees it will not need to respond to the function transition. Event is
a pointer to the struct inputevent which reports the transition.
seln_report_event () generates a corresponding call to
seln_inf orm (), and, if the returned struct is not null, passes it to the client’s
function_proc callback procedure (described above under Callback Procedures).
SELN_REPORT is a macro which takes just an input-event pointer, and calls
seln_report_event with 0 as a first argument.
Nr microsystems
Revision A, of May 9, 1988
Chapter 9 — The Selection Service and Library 119
Seln__result
seln_request(holder, buffer)
Seln_holder ^holder;
Seln_request ^buffer;
Seln_request is the low-level (policy-independent) mechanism for retrieving
information about a selection from the process which holds it. Most clients will
access it only indirectly, through seln_ask or seln_query.
Seln_request takes a pointer to a holder (as returned by seln_inquire),
and a request constructed in *buf f er . The request is transmitted to the indi¬
cated selection holder, and the buffer rewritten with its response. Failures in the
RPC mechanism will cause a SELN_FAILED return; if the process of the
addressed holder is no longer active, the return value will be
SELN__NON__EXIST.
Clients which call seln_request directly will find it most convenient to ini¬
tialize the buffer by a call to seln__init_request.
Request attributes which are not recognized by the selection holder will be
returned as the value of the attribute SELN_UNRECOGNIZED. Responses
should be provided in the order requests were encountered.
int
seln_same_holder(holder1, holder2)
Seln_holder *holderl, *holder2;
This predicate returns TRUE if holder 1 and holder 2 refer to the same selec¬
tion client.
int
seln_secondary_exists(buffer)
Seln__function_buf fer *buf fer;
This predicate returns TRUE if the function buffer indicates that a secondary
selection existed at the time the function key went up.
int
seln_secondary_made(buffer)
Seln_function_buffer *buffer;
This predicate returns TRUE if the function buffer indicates that a secondary
selection was made some time since the function key went down (although it
may have been cancelled before the key went up).
void
seln_use__test_service ()
microsystems
Revision A, of May 9, 1988
120 Sun View 1 System Programmer’s Guide
The application is set to communicate with a test version of the Selection Ser¬
vice, rather than the standard production version. This call should be made
before any selection client is created; this normally means before subwindows in
the application process are created.
void
seln_use_timeout(seconds)
int seconds;
The default timeout on subsequent RPC calls from this process is changed to be
seconds long.
void
seln_yield_all()
This procedure inquires the holders of all selection, and for each which is held by
a client in the calling process, sends a yield request to that client and a Done to
the service. It should be called by applications which are about to exit, or to
undertake lengthy computations during which they will be unable to respond to
requests concerning selections they hold.
Revision A, of May 9,1988
Chapter 9 — The Selection Service and Library 121
9.9. Common Request
Attributes
The following is an annotated listing of
<suntool/selection attributes.h>.
/* @(#)selection_attributes.h 1.10 85/09/05 */
fifndef suntool_selection_attributes_DEFINED
fdefine suntool_selection_attributes_DEFINED
/*
* Copyright (c) 1985 by Sun Microsystems, Inc.
*/
♦include <sunwindow/attr.h>
/*
* Common requests a client may send to a selection-holder
*/
fdefine ATTR_PKG_SELECTION ATTR_PKG_SELN_BASE
fdefine SELN_ATTR(type, n) ATTR(ATTR_PKG_SELECTION, type, n)
fdefine SELN_ATTR_LIST (list__type, type, n) \
ATTR(ATTR_PKG_SELECTION, ATTR_LIST_INLINE(list_type, type), n)
Revision A, of May 9,1988
122 SunView 1 System Programmer’s Guide
/*
* Attributes of selections
*/
typedef enum {
/* Simple attributes
*/
SELN_REQ_BYTESIZE = SELN_ATTR (ATTR_INT, D r
/* value is an int giving the number of bytes in the
* selection's ascii contents */
S E LN_REQ_CONT ENT S_AS C11 = SELN_ATTR_LIST(ATTR_NULL, ATTR_CHAR, 2),
/* value is a null-terminated list of 4-byte words containing
* the selection's ascii contents. The last word containing
* a character of the selection should be followed by a
* terminator word whose value is 0. If the last word of
* contents is not full, it should be padded out with NULs */
SELN_REQ_CONTENTS_PIECES = SELN__ATTR_LIST (ATTR_NULL, ATTR_CHAR, 3),
/* value is a null-terminated list of 4-byte words containing
* the selection's contents described in the textsw's
* piece-table format. */
S E LN_REQ_FIRS T = SELN_ATTR(ATTR_INT, 4),
/* value is an int giving the number of bytes which precede
* the first byte of the selection. */
S E LN_REQ_F IRS T_UN IT = SELN_ATTR (ATTR_INT, 5),
/* value is an int giving the number of units of the selection's
* current level (line, paragraph, etc.) which precede the
* first unit of the selection.
S E LN_REQ_L AS T = SELN_ATTR (ATTR_INT,
/* value is an int giving the byte index of the last byte
* of the selection.
SELN_REQ_LAST_UNIT = SELN_ATTR (ATTR_INT,
/* value is an int giving the unit index of the last unit
* of the selection at its current level.
SELN_REQ_LEVEL = SELN_ATTR(ATTR_INT,
/* value is an int giving the current level of the selection
* (See below for #defines of the most useful levels.)
*/
6 ),
*/
7 ) ,
*/
8 ) ,
*/
SELN_REQ_FILE_NAME = SELN_ATTR_LIST (ATTR__NULL, ATTR__CHAR, 9),
/* value is a null-terminated list of 4-byte words containing
* the name of the file which holds the selection (when the
* Selection Service has been asked to hold a selection).
* The string is represented exactly like ascii contents. */
microsystems
Revision A, of May 9, 1988
Chapter 9 — The Selection Service and Library 123
/* Simple commands (no parameters)
*/
S E LN_RE Q_COMMIT_P ENDING_DE LETE
= SELN__ATTR (ATTR_N0_VALUE, 65),
/* There is no value. The replier is instructed to delete any
* secondary selection made in pending delete mode. */
SELN_REQJDELETE = S E LN_AT T R(ATTR_N0_VALUE, 66),
/* There is no value. The replier is instructed to delete the
* selection referred to in this request. */
SELN_REQ_RESTORE = SELN__ATTR (ATTR_N0__VALUE, 67),
/* There is no value. The replier is instructed to restore the
* selection referred to in this request, if it has maintained
* sufficient information to do so. */
/* Other commands
*/
SELN_REQ_YIELD = SELN_ATTR (ATTR_ENUM, 97),
/* The value in the request is not meaningful; in the response,
the value is a Seln_result which is the replier's
return code. The replier is requested to yield the
selection referred to in this request. SELN_SUCCESS,
SELN_DIDNT_HAVE, and SELN_WRONG_RANK are legitimate
responses (the latter comes from a holder asked to
yield the primary selection when it knows a function-key
is down). */
SELN_REQ_FAKE_LEVEL = SELN_ATTR (ATTR_INT, 98),
/* value is an int giving a level to which the selection
should be expanded before processing the remainder of
this request. The original level should be maintained
on the display, however, and restored as the true level
on completion of the request */
SELN_REQ__SET_LEVEL = SELN_ATTR (ATTR_INT, 99),
value is an int giving a level to which the selection
should be set. This request should affect the true level */
/*
★
/* Service debugging commands
*/
S E LN_T RACE_ACQU I RE = SELN__ATTR (ATTR_BOOLEAN, 193),
SELN_TRACE_DONE = SELN_ATTR(ATTR_BOOLEAN, 194),
S E LN_T RACE_HO LD__F I LE = SELN_ATTR (ATTR_BOOLEAN, 195),
SELN_TRACE__INFORM = SELN__ATTR (ATTR_BOOLEAN, 19 6),
SELN_TRACE_INQUIRE = SELN__ATTR (ATTR_BOOLEAN, 197),
S E LN_T RACE_YIELD = SELN_ATTR(ATTR_BOOLEAN, 198),
SELN_TRACE_STOP = SELN_ATTR(ATTR_BOOLEAN, 199),
/* value is a boolean (TRUE / FALSE) indicating whether calls
* to that procedure in the service should be traced.
* TRACE_INQUIRE also controls tracing on seln_inquire all(). */
SELN_TRACE_DUMP = SELN_ATTR (ATTR_ENUM, ~ 200),
/* value is a Seln_rank, indicating which selection holder
should be dumped; SELN_UNSPECIFIED indicates all holders. */
fsun
Nr microsystems
Revision A, of May 9, 1988
124 Sun View 1 System Programmer’s Guide
/* Close bracket so replier can terminate commands
* like FAKE_LEVEL which have scope
*/
SELN_REQ_END_REQUEST = SELN_ATTR (ATTR_NO_VALUE,
/* Error returnd for failed or unrecognized requests
*/
SELN_REQ_UNKNOWN = SELN_ATTR (ATTRJENT,
S E LN_RE Q_F AI LED = SELN__ATTR (ATTR_INT f
} Seln attribute;
/* Meta-levels available for use with SELN__REQ_FAKE/SET_LE VEL.
* SELN__LEVEL_LINE is "text line bounded by newline characters,
* including only the terminating newline”
*/
typedef enum {
S E LN_LE VE L__F IRS T
SELN_LEVEL_LINE
S E LN_LE VE L_AL L
SELN_LEVEL_NEXT
S E LN_LE VE L_P RE VIOU S
} Seln_level;
#endif
0x40000001,
0x40000101,
0x40008001,
0x4000F001,
0x4000F002
253),
254) ,
255)
^§un
Revision A, of May 9, 1988
Chapter 9 — The Selection Service and Library 125
9.10. Two Program
Examples
There are several programs in the SunView 1 Programmer* s Guide that do a
seln_ask () for the primary selection. Here are two sample programs that
manipulate the selection in more complex ways.
get_selection Code The following code is from the program get_s election, which is part of the
release. This program copies the contents of the desired SunView selection to
stdout. For more information, consult the get__select ion(l) man page.
#ifndef lint
static char sccsid[] = (#)get_selection.c 10.5 86/05/14";
#endif
/*
* Copyright (c) 1986 by Sun Microsystems, Inc.
*/
#include <stdio.h>
#include <sys/types.h>
#include <suntool/selection_svc.h>
#include <suntool/selection_attributes.h>
static Seln__result read_proc();
static int data read = 0;
static void
quit () ;
#ifdef STANDALONE
main(argc, argv)
#else
get__selection_main (argc
#endif STANDALONE
int
char
{
Seln_client
Seln_holder
Seln_rank
char
int
argv)
argc;
**argv;
client;
holder;
rank = S E LN_P RIMARY;
context = 0;
debugging = FALSE;
while (—argc) {
/* command-line args control rank of desired selection,
/* use of a debugging service, and rpc timeout
argv++;
switch (**argv) {
case '1' :
rank = S E LN_P RIMARY;
break;
case '2' :
rank = S E LN_S E CONDARY;
*/
*/
W sun
\r microsystems
Revision A, of May 9,1988
126 Sun View 1 System Programmer’s Guide
break;
case '3':
rank = SELN__SHELF;
break;
case 'D':
seln_use_test_service () ;
break;
case 't':
case 'T':
seln__use_timeout (atoi (++argv) ) ;
—argc;
break;
default:
quit("Usage: get_selection [D] [t seconds] [1 I 2 |3]\n");
}
}
/* find holder of desired selection */
holder = seln__inquire (rank) ;
if (holder, state — SELN__NONE) {
quit("Selection non-existent, or selection-service failure\n");
}
/* ask for contents, and let callback proc print them */
(void) seln_query(&holder, read_proc, &context,
SELN__REQ_CONTENTS_ASCI 1, 0, 0);
if (data__read)
exit (0);
else
exit (1);
}
static void
quit(str)
char *str;
{
fprintf(stderr, str);
exit(1);
>
/*
* Procedure called with each buffer of data returned in response
* to request transmitted by seln_query.
*/
static Seln_result
read_proc(buffer)
Seln_request ^buffer;
{
char *reply;
/* on first buffer, we have to skip the request attribute,
* and then make sure we don't repeat on subsequent buffers
*/
w sun
\r microsystems
Revision A, of May 9, 1988
Chapter 9 — The Selection Service and Library 127
if (*buffer->requester.context == 0) {
if (buffer == (Seln_request *) NULL ||
*((Seln_attribute *) buffer->data) != SELN_REQ_CONTENTS_ASC11) {
quit("Selection holder error — unrecognized request\n");
reply = buffer->data + sizeof (Seln_attribute);
*buffer->requester.context = 1;
} else {
reply = buffer->data;
}
fputs(reply, stdout);
fflush(stdout);
data__read = 1;
return SELN_SUCCESS;
Revision A, of May 9, 1988
128 SunView 1 System Programmer’s Guide
seln demo
Large Selections
The following program, seln demo gets the selection, but it also sets the selec¬
tion and responds to appropriate queries about it. It isn’t an entirely realistic pro¬
gram, since it doesn’t provide selection feedback or use function keys.
It displays a panel with several choices and buttons and a text item. You choose
the rank of the selection you wish to set or retrieve first. If you are setting the
selection, you may also choose whether you want to literally set the selection or
provide the name of a file which contains the selection. Then either type in the
selection and push the Set button, or just push the Get button to retrieve the
current selection of the type you chose.
The code has three logical sections: the procedures to create and service the
panel, the code to set a selection, and the code to get a selection. The routines to
set and get the selection are complicated because they are written to allow arbi¬
trary length selections. Try selecting a 3000 byte piece of text; although you can
only see 10 characters of it in the text panel item, the entire selection can be
retrieved and/or set.
In order to handle large selections, the selection service breaks them into smaller
chunks of about 2000 bytes called buffers. The routines you write must be able
to handle a buffer and save enough information so that when they are called
again with the next buffer, they can pick up where they left off. seln_demo uses
the context fields provided in the Selection Service data structures to accomplish
this.
microsystems
Revision A, of May 9,1988
Chapter 9 — The Selection Service and Library 129
#ifndef lint
static char sccsid[] = (#)seln_demo.c 1.5 88/03/14 Copyr 1986 Sun Micro";
#endif
/*
* selnjiemo. c
★
* demonstrate how to use the selection service library
*/
#include <stdio.h>
#include <suntool/sunview.h>
#include <suntool/panel.h>
#include <suntool/seln.h>
static Frame frame;
static Panel panel;
int err =0;
char *malloc();
/*
* definitions for the panel
*/
static Panel_item text__item, type_item, source_item, mesg_item;
static Panel__item set_item[3], get_item[3];
static void set__button_proc () , get button ^p roc () , change label_proc () ;
#define PRIMARY_CHOICE 0
#define SECONDARY__CHOICE 1
tdefine SHELF_CHOICE 2
#define ITEM_CHOICE 0
#define FROMFILE CHOICE 1
int selection_type = PRIMARY_CHOICE;
int selection_source = ITEM CHOICE;
/* get/set the primary selection */
/* get/set the secondary selection */
/* get/set the shelf */
/* use the text item literally as the
selection */
/* use the text item as the name of a
file which contains the selection */
char *text_labels[3][2] = {
{ "
"New primary selection
"File containing new primary selection:"
},
{
"New secondary selection
"File containing new secondary selection:
},
{
"New shelf:" f
"File containing new shelf:"
m sun
\r microsystems
Revision A, of May 9, 1988
130 SunView 1 System Programmer’s Guide
};
char *mesg__labels [3] [2] = {
{ "
},
{
},
{
"Type in a selection and hit the Set Selection button”,
"Type in a filename and hit the Set Selection button"
"Type in a selection and hit the Set Secondary button",
"Type in a filename and hit the Set Secondary button"
"Type in a selection and hit the Set Shelf button ”,
"Type in a filename and hit the Set Shelf button"
};
Seln_rank type_to_rank[3] = { SELN_PRIMARY, SELN_SECONDARY, SELN_SHELF };
/*
* definitions for selection service handlers
*/
static Seln_client s_client; /* selection client handle */
#define FIRST_BUFFER 0
#define NOT FIRST BUFFER 1
char ^selection bufs[3];
/* contents of each of the three selections;
they are set only when the user hits a set
or a get button */
int f unc__key_jproc () ;
Seln__result reply_j?roc ()
Seln_result read_j>roc () ;
Revision A, of May 9, 1988
Chapter 9 — The Selection Service and Library 131
/********************************************************************/
/* main routine */
/********************************************************************/
main(argc, argv)
int argc;
char **argv;
{
/* create frame first */
frame = window__create (NULL, FRAME,
FRAME_ARGS, argc, argv,
WIN_ERROR__MSG, "Cannot create frame”,
F RAME_L ABE L, ” seln_demo",
0 ) ;
/* create selection service client before creating subwindows
(since the panel package also uses selections) */
s_client = seln_create (func_key_j?roc, reply_j?roc, (char *) 0);
if (s___client == NULL) {
fprintf(stderr, "seln_demo: seln_create failed!\n”);
exit(1);
}
/* now create the panel */
panel = window_create(frame, PANEL,
WIN_ERROR_MSG, "Cannot create panel",
0 );
init__panel (panel) ;
window_fit_height(panel);
window_fit_height(frame);
window_main_loop(frame);
/* yield any selections we have and terminate connection with the
selection service */
seln__destroy (s_client) ;
}
m sun
\r microsystems
Revision A, of May 9, 1988
132 Sun View 1 System Programmer’s Guide
/***********************************************************************/
/* routines involving setting a selection */
/***********************************************************************/
/*
* acquire the selection type specified by the current panel choices;
* this will enable requests from other clients which want to get
* the selection's value, which is specified by the source_item and text__item
*/
static void
set_button_jproc (/* args ignored */)
{
Seln_rank ret;
char *value = (char *) panel__get__value (text__item) ;
if (select ion_source == FROMFILE__CHOICE) {
/* set the selection from a file; the selection service will
actually acquire the selection and handle all requests */
if (seln_hold_f ile (type_to_rank [selection__type], value)
!= SELN_SUCCESS) {
panel_set (mesg_item, PANEL_LABEL_STRING,
"Could not set selection from named file!”, 0);
err++;
} else if (err) {
panel_set (mesg___item, PANEL_LABEL_STRING,
mesg_labels [selection_type] [selection_source], 0) ;
err = 0;
}
return;
)
ret = seln_acquire (s__client, type__to_rank [ selection_type]) ;
/* check that the selection rank we received is the one we asked for */
if (ret != type_to__rank [selection__type] ) {
panel_set (mesg_item, PANEL_LABEL_STRING,
"Could not acquire selection!", 0);
err++;
return;
}
set_selection_value(selection_type, selection_source, value);
}
/*
* copy the new value of the appropriate selection into its
* buffer so that if the user changes the text item and/or the current
* selection type, the selection won't mysteriously change
*/
set_selection_value(type, source, value)
W sun
\r microsystems
Revision A, of May 9, 1988
Chapter 9 — The Selection Service and Library 133
int type, source;
char *value;
{
if (selection__bufs [type] != NULL)
free(selection_bufs[type]);
selection__buf s [type] = malloc (strlen (value) + 1) ;
if (selection_bufs[type] == NULL) {
panel__set (mesg_item, PANEL_LABEL__STRING, "Out of memory!",
errH;
} else {
)
strcpy (selection__bufs [type],
if (err) {
panel_set (mesg_item,
err = 0;
}
value);
PANEL_LABEL_STRING,
mesg_labels[type][source].
0 ) ;
0 );
/*
* func_key_proc
★
* called by the selection service library whenever a change in the state of
* the function keys requires an action (for instance, put the primary
* selection on the shelf if the user hit PUT)
*/
func__key_proc (client_data, args)
char *client_data;
Seln_function_buffer *args;
{
Seln_holder ^holder;
/* use seln_figure_response to decide what action to take */
switch (seln_figure_response(args, Sholder)) {
case SELN_IGNORE:
/* don't do anything */
break;
case SELN_REQUEST:
/* expected to make a request */
break;
case SELN_SHELVE:
/* put the primary selection (which we should have) on the
shelf */
if (seln__acquire (s_client, SELN_SHELF) != SELN_SHELF) {
panel_set (mesg_item, PANEL_LABEL_STRING,
"Could not acquire shelf!", 0);
err++;
} else {
shelve_primary_selection();
}
break;
W sun
\r microsystems
Revision A, of May 9, 1988
134 SunView 1 System Programmer’s Guide
case SELN_FIND:
/* do a search */
break;
case SELN_DELETE:
/* do a delete */
break;
shelve_primary_selection()
char *value = selection_bufs[PRIMARY_CHOICE];
if (selection_bufs [SHELF__CHOICE] != NULL)
free (selectionjoufs [SHELF_CHOICE] ) ;
selection_bufs[SHELF_CHOICE] = malloc(strlen(value)+1);
if (selection_bufs[SHELF_CHOICE] == NULL) {
panel_set (mesg_item, PANEL_LABEL_STRING, "Out of memory!", 0) ;
err++;
} else {
strcpy(selection_bufs [SHELF_CHOICE] , value) ;
/*
* reply_j>roc
* called by the selection service library whenever a request comes from
* another client for one of the selections we currently hold
*/
Seln_result
reply_proc(item, context, length)
Seln__attribute item;
Seln_replier_data ^context;
int length;
{
int size, needed;
char *seln, *destp;
/* determine the rank of the request and choose the
appropriate selection */
switch (context->rank) {
case SELN PRIMARY:
seln = selection_bufs[PRIMARY_CHOICE];
break;
case SELN SECONDARY:
seln = selection_bufs[SECONDARY_CHOICE];
break;
case SELN SHELF:
seln = selection_buf s [SHELF__CHOICE] ;
break;
A sun
Xr microsystems
Revision A, of May 9, 1988
Chapter 9 — The Selection Service and Library 1 35
default:
seln = NULL;
}
/* process the request */
switch (item) {
case SELN_REQ_CONTENTS_ASCII:
/* send the selection */
/* if context->context == NULL then we must start sending
this selection; if it is not NULL, then the selection
was too large to fit in one buffer and this call must
send the next buffer; a pointer to the location to start
sending from was stored in context->context on the
previous call */
if (context->context == NULL) {
if (seln == NULL)
return (SELN_DIDNT__HAVE) ;
context->context = seln;
}
size = strlen(context->context);
destp = (char *)context->response_pointer;
/* compute how much space we need: the length of the selection
(size) , plus 4 bytes for the terminating null word, plus 0
to 3 bytes to pad the end of the selection to a word
boundary */
needed = size + 4;
if (size % 4 != 0)
needed += 4 - size % 4;
if (needed <= length) {
/* the entire selection fits */
strcpy(destp, context->context);
destp += size;
while ((int)destp % 4 != 0) {
/* pad to a word boundary */
*destp++ = '\0';
}
/* update selection service's pointer so it can
determine how much data we are sending */
context->response_pointer = (char **)destp;
/* terminate with a NULL word */
*context->response_pointer++ = 0;
return(SELN_SUCCESS);
} else {
/* selection doesn't fit in a single buffer; rest
will be put in different buffers on subsequent
calls */
strncpy(destp, context->context, length);
destp += length;
m sun
V microsystems
Revision A, of May 9, 1988
136 Sun View 1 System Programmer’s Guide
context->response_j?ointer = (char **)destp;
context->context += length;
return(SELN_CONTINUED);
}
case SELN_REQ_YIELD:
/* deselect the selection we have (turn off highlight, etc.) */
*context->response_pointer++ = (char *)SELN_SUCCESS;
return(SELN_SUCCESS);
case SELN_REQ_BYTESIZE:
/* send the length of the selection */
if (seln == NULL)
return(SELN_DIDNT_HAVE) ;
*context->response_j?ointer++ = (char *)strlen(seln);
return(SELN_SUCCESS);
case SELN__REQ_END_REQUEST :
/* all attributes have been taken care of; release any
internal storage used */
return(SELN_SUCCESS);
break;
default:
/* unrecognized request */
return(SELN_UNRECOGNIZED);
}
/* NOTREACHED */
m sun
\r microsystems
Revision A, of May 9, 1988
Chapter 9 — The Selection Service and Library 1 37
/*******************************************************************/
/* routines involving getting a selection */
/*******************************************************************/
/*
* get the value of the selection type specified by the current panel choices
* from whichever client is currently holding it
*/
static void
get_button_proc(/* args ignored */)
{
Seln__holder holder;
int len;
char context = FIRST__BUFFER; /* context value used when a very long
message is received; see procedure
comment for read_j?roc */
if (err) {
panel_set (mesg_item, PANEL_LABEL_STRING,
mesg_labels [selection_type] [selection_source], 0) ;
err = 0;
}
/* determine who has the selection of the rank we want */
holder = seln_inquire (type_to__rank [selection_type]) ;
if (holder.state == SELN_NONE) {
panel__set (mesg__item, PANEL_LABEL_STRING,
"You must make a selection first!", 0);
err++;
return;
}
/* ask for the length of the selection and then the actual
selection; read_jproc actually reads it in */
(void) seln_query(&holder, read_proc, Scontext,
S E LN__REQ_B YTE SIZ E, 0,
SELN_REQ_CONTENTS_ASCII, 0,
0 ); "
/* display the selection in the panel */
len = strlen (selection_bufs [selection__type]) ;
if (len > (int) panel_get (text_item, PANEL_VALUE_STORED_LENGTH) )
panel_set (text__item, PANEL_VALUE_STORED_LENGTH, len, 0) ;
panel_set_value (text___item, selection_bufs [selection_type]) ;
}
/*
* called by seln_query for every buffer of information received; short
m sun
\r microsystems
Revision A, of May 9, 1988
138 Sun View 1 System Programmer* s Guide
* messages (under about 2000 bytes) will fit into one buffer; for larger
* messages, read__proc will be called with each buffer in turn; the context
* pointer passed to seln_query is modified by read_j?roc so that we will know
* if this is the first buffer or not
*/
Seln_result
read_proc(buffer)
Seln_request ^buffer;
{
char *reply; /* pointer to the data in the buffer received */
unsigned len; /* amount of data left in the buffer */
int bytes_to__copy;
static int selection_have_bytes; /* number of bytes of the selection
which have been read; cumulative over all calls for
the same selection (it is reset when the first
buffer of a selection is read) */
static int selection_len; /* total number of bytes in the current
selection */
if (*buffer->requester.context == FIRST_BUFFER) {
/* this is the first buffer */
if (buffer == (Seln__request *)NULL) {
panel_set (mesg_item, PANEL__LABEL_STRING,
"Error reading selection - NULL buffer", 0) ;
err++;
return(SELNJJNRECOGNIZED);
)
reply = buffer->data;
len = buffer->buf_size;
/* read in the length of the selection */
if (*( (Seln_attribute *)reply) != SELN_REQ_BYTESIZE) {
panel_set (mesg_item, PANEL__LABEL_STRING,
"Error reading selection - unrecognized request",
0 );
errH;
return(SELNJJNRECOGNIZED);
)
reply += sizeof (Seln__attribute) ;
len = buf fer->buf_size - sizeof (Seln__attribute) ;
selection_len = Mint *) reply;
reply += sizeof(int); /* this only works since an int is 4
bytes; all values must be padded to
4-byte word boundaries */
len -= sizeof(int);
/* create a buffer to store the selection */
if (selection_bufs[selection_type] != NULL)
» sun
Nr microsystems
Revision A, of May 9, 1988
Chapter 9 — The Selection Service and Library 139
free(selection_bufs[selection_type]);
selection_bufs[selection_type] = malloc(selection_len + 1);
if (selection_bufs[selection_type] == NULL) {
panel__set (mesg_item, PANEL_LABEL_STRING,
"Out of memory!”, 0);
err++;
return (SELN__FAILED) ;
}
selection_have_bytes = 0;
/* start reading the selection */
if (*(Seln_attribute *)reply != SELN_REQ_CONTENTS_ASCII) {
panel_set (mesg_item, PANEL_LABEL_STRING,
"Error reading selection - unrecognized request",
0 ) ;
errH;
return (SELNJJNRECOGNIZED) ;
}
reply += sizeof(Seln_attribute);
len -= sizeof(Seln__attribute);
*buffer->requester.context = NOT_FIRST_BUFFER;
) else {
/* this is not the first buffer, so the contents of the buffer
is just more of the selection */
reply = buffer->data;
len = buf fer->buf__size;
}
/* copy data from the received buffer to the selection buffer
allocated above */
bytes_to_copy = selection_len - selection_have_bytes;
if (len < bytes_to_copy)
bytes_to__copy = len;
strncpy(&selection_bufs[selection_type][selection_have__bytes],
reply, bytes_to_copy);
selection_have_bytes += bytes_to_copy;
if (selection_have_bytes == selection_len)
selection_bufs[selection_type][selection_len] = 'Non¬
return (SELN_SUCCESS) ;
}
W sun
\r microsystems
Revision A, of May 9, 1988
140 Sun View 1 System Programmer’s Guide
/***********************************************************/
/* panel routines */
/***********************************************************/
/* panel initialization routine */
init_panel(panel)
Panel panel;
{
mesg_item = panel_create__item (panel, PANEL_MESSAGE,
P ANE L__L AB E L_S T RING,
mesg_labels [PRIMARY__CHOICE] [ITEM_CHOICE] ,
0 ) ;
type_item = panel_create_item(panel, PANEL_CYCLE,
PANEL_LABEL_STRING, "Set/Get: ",
PANEL_CHOICE_STRINGS, "Primary Selection",
"Secondary Selection",
"Shelf",
PANEL_NOTIFY_PROC,
P ANE L_L AB E L_X,
PANEL_LABEL__Y,
0 );
0 r
change_label__proc,
ATTR_COL(0),
ATTR_ROW(l),
source_item = pane l__create_i tern (panel, PANEL__CYCLE,
PANEL__LABEL_STRING, "Text item contains:",
PANEL_CHOICE_STRINGS, "Selection",
"Filename Containing Selection",
0 ,
P AN E L__N 0 TIF Y_P ROC, change_label _proc,
0 );
text__item = panel__create_item(panel, PANEL_TEXT,
set_item[0]
set_item[l]
set item[2]
PANEL_LABEL_STRING,
text_labels [PRIMARY_CHOICE] [ ITEM__CHOICE]
P ANE L__VALUE_D ISP L AY_LEN GT H, 2 0,
0 ) ;
= panel_create__item (panel,
P ANEL_LABEL_IMAGE,
P ANE L_NOT IF Y__P ROC,
P ANE L_L ABE L_X ,
PANEL__LABEL_Y,
0 ) ;
= panel_create_item(panel,
P ANEL_LABEL_IMAGE,
P ANE L_N 0 TIF Y_P ROC,
P ANE L_L AB E L__X ,
P ANE L_L ABE L__Y,
PANEL_SHOW_ITEM,
0 ) ;
= panel_create_item (panel,
P ANEL_LABEL_IMAGE,
PANEL__BUTTON,
panel_button__image (panel
"Set Selection",
set_button_j>roc,
ATTR__COL (0) ,
ATTR_ROW(5),
PANE L_BUT TON,
panel_button_image(panel
"Set Secondary",
set_button_proc,
ATTR__COL (0) ,
ATTR_ROW(5),
FALSE,
PANEL_BUTTON,
panel_button_image(panel
"Set Shelf", 15,
15,0),
15,0),
m sun
Xr microsystems
Revision A, of May 9, 1988
Chapter 9 — The Selection Service and Library 141
}
get_item[0]
get_item[l]
get__item [2]
P ANE L_NOT IF Y_P ROC,
P ANE L_LABE L__X,
PANE L_L ABE L__Y,
PANE L_S HOW_ITEM,
0 );
= panel_create_item (panel,
P ANE L_JL AB E L_ I MAGE ,
PANE L_NOT IF Y_P ROC,
PANEL_LABEL_X,
P ANE L__L ABE L_Y,
0 );
= panel_create_item (panel,
PANE L__LABEL_ IMAGE,
P AN E L_N 0 TIF Y_P ROC,
PANEL_SHOW_ITEM,
P ANE L_L ABE L_X,
P ANE L__L AB E L_Y,
0 ) ;
= panel_create_item (panel,
P ANEL_LABEL_IMAGE,
PANE L__NOT IF Y_P ROC,
PANEL_SHOW_ITEM,
P ANE L_L ABE L__X,
P ANE L_L AB E L_Y,
0 );
set__button_proc,
ATTR_COL(0) ,
ATTR_ROW(5),
FALSE,
PANEL_BUTTON,
panel_button_image(panel,
"Get Selection”, 15,0),
get_button_proc,
ATTR_COL(20) ,
ATTR_ROW(5),
PANEL_BUTTON,
panel_button_image(panel,
"Get Secondary", 15,0),
get_button_proc,
FALSE,
ATTR_COL(20) ,
ATTR_ROW(5),
PANEL_BUTTON,
panel_button_image(panel,
"Get Shelf", 15,0),
get__butt on_proc,
FALSE,
ATTR_COL(20) ,
ATTR_ROW(5),
/*
* change the label of the text item to reflect the currently chosen selection
* type
*/
static void
change_label_j?roc(item, value, event)
Panel_item item;
int value;
Event *event;
{
int old_selection_type = selection_type;
selection_type = (int)panel_get_value(type_item);
selection_source = (int)panel_get_value(source_item); ^
panel_set (text_item, PANEL_LABEL_STRING,
text_labels [selection_type] [selection__source], 0) ;
panel_set (mesg_item, PANEL_LABEL__STRING,
mesg_labels [selection_type] [selection_source], 0) ;
if (old__selection_type != selection_type) {
panel___set (set_item [old___selection_type],
PANEL_SHOW_ITEM, FALSE, 0) ;
panel_set (set_item[selection_type],
W sun
\r microsystems
Revision A, of May 9,1988
142 SunView 1 System Programmer’s Guide
}
PANEL_SHOW_ITEM, TRUE, 0);
panel_set(get_item[old_selection_type],
PANEL_SHOW_ITEM, FALSE, 0);
panel_set(get_item[selection_type],
PANEL SHOW ITEM, TRUE, 0);
V microsystems
Revision A, of May 9,1988
The User Defaults Database
The User Defaults Database. 145
Why a Centralized Database?. 145
10.1. Overview. 146
Master Database Files. 146
Private Database Files. 146
10.2. File Format. 147
Option Names. 147
Option Values. 148
Distinguished Names. 148
$Help. 148
$Enumeration. 148
$Message. 149
10.3. Creating a . d File: Example . 149
10.4. Retrieving Option Values. 150
Retrieving String Values. 150
Retrieving Integer Values. 150
Retrieving Character Values. 151
Retrieving Boolean Values. 151
Retrieving Enumerated Values. 15 2
Searching for Specific Symbols. 152
Searching for Specific Values. 153
Retrieving all Values in the Database. 153
10.5. Conversion Programs. 154
10.6. Property Sheets. 155
10.7. Error Handling. 156
Error Action . 156
MaximumErrors . 157
TestMode . 157
10.8. Interface Summary. 157
10.9. Example Program: filer Defaults Version. 160
The User Defaults Database
Many UNIX programs are customizable in that the user can modify their behavior
by setting certain parameters checked by the program at startup time. This
approach has been extended in SunView to include facilities used by many appli¬
cations, such as menus, text and scrollbars, as well as applications.
The SunView user defaults database is a centralized database for maintaining
customization information about different programs and facilities.
This chapter is addressed to programmers who want their programs to make use
of the defaults database. For a discussion of the user interface to the defaults
database, read the def aultsedit(l) manual page in the SunOS Reference
Manual and see the section on def aultsedit in the SunView 1 Beginner’s
Guide.
In this chapter, customizable parameters are referred to as options-, the values
they can be set to are referred to as values.
All definitions necessaiy to use the defaults database may be obtained by includ¬
ing the file <sunwindow/def aults . h>.
Why a Centralized Database? Traditionally, each customizable program has a corresponding customization file
in the user’s home directory. The program reads its customization file at startup
time to get the values the user has specified.
Examples of customizable programs are mail(l), csh(l), and sunview(l).
The corresponding customization files are .mailrc, . cshrc, and-
. sunview.
While this method of handling customization works well enough, it can become
confusing to the user because:
□ Since the information is scattered among programs, it’s difficult for the user
to determine what options she or he can set.
□ Since the format of each customization file is different, the user must find
and read documentation for each program he or she wants to customize.
□ Even after the user has located the customization file and become familiar
with its format, it’s often difficult for the user to determine what the legal
values are for a particular option.
microsystems
145
Revision A, of May 9,1988
146 Sun View 1 System Programmer’s Guide
10.1. Overview
Master Database Files
Private Database Files
SunView addresses these problems by providing a centralized database which
can be used by any customizable program. The user can view and modify the
options in the defaults database with the interactive program
defaultsedit(l).
The defaults database actually consists of a single master database and a private
database for each user.
The master database contains all the options for each program which uses the
defaults database. For each option, the default value is given.
The user’s private database contains the values she or he has specified using
def aultsedit. An option’s value in the private database takes precedence
over the option’s default value in the master database.
Application programs retrieve values from the database using the routines
described later in this chapter. These routines first search the user’s private data¬
base for the value. If the value is not found in the private database, then the
default value from the master database is returned. Each of these routines
specify a fall-back default value which is used if neither database contains the
value. It should match the value in the master database.
The master database is stored in the directory /usr/lib/defaults as a
number of individual files, each containing the options for one program or pack¬
age. These files are created with a text editor by the author of the program or
package; see Section 10.3, Creating a . d File: Example , later in this chapter.
By convention, the file name is the capitalized name of the program or package,
with the suffix . d — Mail. d, SunView. d, Menu . d, etc.
The defaults database itself has two options you can set using def aultsedit
to control where the master database resides:
□ Directory is provided so that a group may have its own master database
directory in which to do development independently of the standard
/usr/lib/defaults directory.
□ Private Directory is provided so that an individual developer may have his
own private master database for development. Note that this directory must
have copies (or symbolic links) to all of the . d files in
/usr/lib/def aults, or accesses to the absent files will result in run¬
time errors.
When the master database is accessed, the defaults routines look for the appropri¬
ate . d file first in the Private directory (if specified). If the file is not found or
the directory not specified, then if a Directory is specified it is searched, other¬
wise the default directory, /usr/lib/def aults, is searched.
A user’s private database is stored in the file .defaults in the user’s home
directory. This is where changes the user makes using def aultsedit are
recorded. 23
23 There is rarely any need for the user to edit his .defaults file by hand — it is automatically created
microsystems
Revision A, of May 9,1988
Chapter 10 — The User Defaults Database 147
10.2. File Format
Option Names
There is an option called Private_only which allows the user to disable the read¬
ing of the master database entirely, thereby reducing program startup time. Note
that for this to work, you must make sure that the fall-back values you specify in
your program exactly match the values in the master database.
The format for both master and private database files is identical.
The first line in the file contains a version number. 24 The rest of the file consists
of a number of lines, each line contains either an option name with its associated
value or a comment, preceded by a semi-colon (;). Blank lines are also legal.
The option names are organized hierarchically, just like files in a file system.
Names must always start with a slash character, (/), and each level in the naming
hierarchy is separated from the previous level by a slash character. Each name
consists of one or more letters (A-Z, a-z), digits (0-9), dollar signs ($), and under¬
scores (_). By convention, the first letter of each name is capitalized. 25
There are two shorthand notations for option names. First, whenever a line does
not start with a slash, the previous node is prepended to the name (this is similar
to the treatment of path names in UNIX). So
/SunView/Font
$Help
is equivalent to
/SunView/Font
/SunView/Font/$Help
The second shorthand convention is that any time two slashes in a row are
encountered, the option name previously defined at that level is assumed. Each
pair of slashes corresponds to one name. So
/SunView/Font
//Walking_Menus
//Icon_gravity
is equivalent to
/SunView/Font
/SunView/Walking_Menus
/SunView/Icon_gravity
and updated by default sedit. The one time the user needs to edit his . de fau It s file by hand is to
disable the defaults Testmode option once it has been enabled. See the discussion in Section 10.7, Error
Handling, below.
24 The version number is included so that if any incompatible changes are made to the default database
format in the future, the library routines can tell when they encounter an older file format.
25 This convention is just for readability — internally all names are converted to lower case, so the defaults
database is insensitive to case.
Asun
XT microsystems
Revision A, of May 9, 1988
148 SunView 1 System Programmer’s Guide
and
/SunView/Font/Bold
///Italic
///Size
is equivalent to
/SunView/Font/Bold
/SunView/Font/Italic
/SunView/Font/Size
Option Values All option values are stored as strings. They have the same syntax as quoted
strings in C. In particular, the backslash character (\) is used as an escape charac¬
ter for inserting other characters into the quoted string. The following backslash
escapes are recognized:
Table 10-1 Defaults Metacharacters
Backslash Escape
Prints as:
\\
Backslash
\"
Double quote
V
Single quote
\n
Newline
\t
Tab
\b
Backspace
\r
Carriage return
\f
Form feed
\ddd
3 digit octal number specifying a single character
Option values can be up to 10,000 characters long.
Distinguished Names There are several distinguished names used by def ault sedit. See the next
section for an example illustrating their usage.
$ He lp $ Help allows you to add an explanatory string to be displayed by
def ault sedit for each option.
$Enumeration An enumerated option is one in which the values are explicitly given, such as
{True, False}, {Yes, No}, {North, South, East, West} etc. 26 The user selects one
of the values using def ault sedit.
The way that def ault sedit knows that it has encountered an enumerated
option is by the level name $Enumerat ion. The values for the enumerated
option follow at the same level. Note that you can specify a help string for the
entire enumerated option, as well as specifying the value.
26 There is no limit to the number of values an enumerated option can have.
microsystems
Revision A, of May 9, 1988
Chapter 10 — The User Defaults Database 149
$Message
10.3. Creating a
Example
$Message allows you to add a one-line message to be displayed by
defaultsedit. Use this to make more readable the display of a category
with many options by setting off related options with blank lines or headings.
. d File: Adding options for a new program to the database corresponds to adding a new
first-level option name in the master database, and appears to the user as a new
category in defaultsedit. You do this by creating the appropriate . d file in
/usr/lib/defaults. If the file is in the correct format, and ends in .d,
then defaultsedit will automatically display it as a new category.
Let’s create such a file for a game called “Space Wars.” The options are: the
number of friendly and enemy ships, whether or not stars attract ships, the name
of the user’s ship, and the direction that ships enter the window from.
To conform to the naming convention for master database files, we add the suffix
. d to the first-level option name, yielding the filename SpaceWar. d:
f -
SunDefaults Version 2
/SpaceWar
$Help
"A space ship battle game"
//Friends
"15"
$Help
"Number of friendly ships"
//Enemies
"15"
$Help
"Number of enemy ships"
//Gravity
"Yes"
$Help
"Affects whether star attract ships"
$Enumeration
ti tt
Yes
n ••
Yes/$Help
"Stars attract ships"
No
•t H
No/$Help
"Ships are immune to attraction"
//Name
"Battlestar"
$Help
"Name of your space ship"
//Direction
"North"
$Help
"Starting window border"
$Enumeration
•• H
North
ii ii
North/$Help
"Ships start at north window border"
South
ii ••
South/$Help
"Ships start at south window border"
East
•i H
East/$Help
"Ships start at east window border"
West
H H
West/$Help
"Ships start at west window border"
Note that the highest-level option name, / SpaceWar, has no associated value,
since it wouldn’t make sense to have one. If a database routine tries to access an
option which has no value, the special string DEFAULTS_UNDEFINED will be
returned.
Revision A, of May 9,1988
150 SunView 1 System Programmer’s Guide
10.4. Retrieving Option
Values
Retrieving String Values
Retrieving Integer Values
A simple programmatic interface is provided to retrieve option values from the
defaults database. All values are stored as strings, and may be retrieved with
def ault s_get_str ing (). For convenience, similar get routines are pro¬
vided to retrieve values as integers, characters, or enumerated types. The get rou¬
tines are described below.
To retrieve a string value, use:
char *
defaults_get_string(option_name, default_value, 0)
char *option_name;
char *default_value;
option_name is the name of the option whose value will be retrieved,
default is a value to return if the option is not found in the database or if the
database itself cannot be accessed for any reason. Note that this value should
match the default value in the master database. The final argument to all
default s_get* () routines is zero. 27 In our Space Wars example in the pre¬
vious section, we would call
-s
ship = defaults_get_string("/SpaceWar/Name",
"Battlestar”, 0);
V_ )
On return, ship would point to the string Battlestar.
Suppose you misspelled the option name Name as Nane. Since
/SpaceWar/Nane is not in the defaults database, the fail-back value of
Battlestar will be returned and an error message may be output. 28
To retrieve an integer value, use:
int
defaults_get_integer(option_name, default_value, 0)
char *option_name;
int default_value;
This function gets the option value associated with option_name, treats it as a
decimal integer, and returns the integer value. For example, the string " 17 "
parses into the number 17 and the string " -12 3 " parses into the number -123.
If option_name can’t be found, or its associated value can’t be parsed, the
integer passed in for def ault_value is returned. For example, the call
defaults_get_integer("/SpaceWar/Enemys", 15, 0);
will return the integer 15, since "Enemies" was misspelled as "Enemys".
27 This third argument is not currently used. It is necessary for compatibility with future releases of the
defaults database package, which may use the third argument to return status information.
28 Whether or not the database retrieval routines generate error messages on error conditions depends on the
setting of the option Error Action. See Section 10.7, Error Handling , below.
microsystems
Revision A, of May 9, 1988
Chapter 10 — The User Defaults Database 151
Retrieving Character Values
Retrieving Boolean Values
The function def aults_get_integer_check () is the same as
def aults_get_integer (), except that it checks that the returned value is
within a specified range:
int
defaults_get_integer_check(option_name, default_value.
min, max, 0)
char *option_name;
int default_value;
int min, max;
If the option value is not between min and max, the integer passed in for
def ault_value is returned and an error message may be output.
To retrieve a character value, use:
defaults_get_character(option_name, default_value, 0)
char *option_name;
char default_value;
def ault s_get_character () returns the first character from the option
value. If the option value contains more than one character, the character passed
in for def ault_value is returned and an error message is output.
To retrieve a boolean value, 29 use:
Bool
defaults_get_boolean(option_name, default_value, 0)
char *option_name;
Bool default_value;
def ault s_get_boolean () returns True if the option value is True, Yes,
Enabled, Set, Activated, or 1 and False if the option value is False,
No, Off, Disabled, Reset, Cleared, Deactivated, or 0. If the option
value is not one of the above, the value passed in for def ault_value is
returned and an error message is output.
29 The definition forBool, found in <sunwindow/sun.h>, is: typedef enum {False = 0,
True - 1} Bool;.
Retrieving Character Values
Retrieving Boolean Values
Revision A, of May 9,1988
152 Sun View 1 System Programmer’s Guide
Retrieving Enumerated Values
Searching for Specific Symbols
You can retrieve enumerated option values with default s_get_string (),
then use strcmp(3) to test which value was returned. As an alternative, you
may find it more convenient to define an enumerated type corresponding to the
option values, and use defaults_get_enum () to return the option value as
the corresponding enum. The definition is:
int
defaults_get_enum(option_name , pairs)
char *option_name;
Defaults_pairs pairs[];
pairs is a pointer to an array of Def aults_pairs which contains name-
value pairs. Def aults_pairs is defined as:
typedef struct {
char *name;
int value;
} Defaults_pairs;
The array passed in as pairs must be null-terminated.
def ault s_get_enum () returns the name associated with the value which
is the current value of the option. If no match is found, the value associated
with the last (null) entry is returned.
The following example, using the direction option for our Space Wars example,
illustrates the usage of default s_get_enum ():
f " .J .1 .
\
typedef enum {North, South, East,
directions dir;
West} directions;
Defaults_j?airs direction_pairs []
’’North”, (int) North,
"South", (int) South,
"East", (int) East,
"West", (int) West,
- {
NULL, (int) North};
/* Error value */
dir = defaults_get_enum("/SpaceWar/Direction", direction_pairs);
v_
_ >
To probe the defaults database to see whether or not a particular symbol is stored
in it, use the def ault s_exists () routine. This routine will return TRUE, if
path_name has a value defined in the defaults database. Otherwise a value of
FALSE will be returned.
- \
Bool flagl = defaults_exists("/SpaceWar/Ship_name", NULL);
Bool flag2 = defaults_exists("/SpaceWar/Fred", NULL);
S___
flagl has a value of TRUE; f lag2 has a value of FALSE.
V microsystems
Revision A, of May 9,1988
Chapter 10 — The User Defaults Database 153
Searching for Specific Values To find the original value of a particular database entry before the client’s per¬
sonalized database overwrites it, use
r ---\
defaults_get_default(path_name, default_value, status)
v___ ,
For example, assume that the master database has the entry
/SpaceWar/ShipName "Lollipop"
and that the client’s private database is
/SpaceWar/ShipName "Death Avenger"
If you call def aults_get_string ("/SpaceWar/ShipName",
"<err>", NULL)" it will return Lollipop. If, however,
the path_name is not in the database, then the default
value will be returned.
Retrieving all Values in the To search the database to find all of the values in the database, use the routines
Database defaults_get_child () and def aults_get_sibling (). The routine
def ault s_get_child (path_name, status) returns the simple name
of the the database entry immediately under path_name. If you use
def aults_get_child ("/SpaceWar", NULL) it will return Ship-
Name. You can use spr intf (3S) to construct the full path name:
—-
char temp[1000], *child;
child = defaults_get_child("/SpaceWar", NULL);
if (child == NULL) {
(void)fprintf(stderr, "Error");
exit(1);
)
sprintf(temp, "%s/%s", "/SpaceWar", child);
V-—__,
temp would contain / SpaceWar/ShipName. A NULL value is returned in
there is no child.
def ault s_get_sibling (path_name, status) returns the simple
name of the next database entry immediately following pathname at the same
level. So, if you use
defaults_get_sibling ("/SpaceWar/ShipName", NULL) it will
return Framus. This can be assembled into a full path name using
sprintf(3S).
char temp[1000], *sibling;
sibling = defaults_get_sibling("/SpaceWar/ShipName");
if (sibling == NULL) {
(void)fprintf(stderr, "Error");
exit(1);
}
sprintf(temp, "%s/%s", "/SpaceWar", sibling);
'v microsystems
Revision A, of May 9,1988
154 Sun View 1 System Programmer’s Guide
The following program will dump the entire contents of the defaults database
along with their associated values.
—
void
dump_defaults(path_name, indent)
char *path_name;
char *indent;
{
char temp[1000];
char *child;
(void)printf("%s%s %s0, indent, path_name,
(defaults_get_string(path_name, "<err>", NULL ));
child = defaults_get_child(path_name, NULL);
if (child == NULL) {
return;
}
len - strlen(indent);
indent[len] = '';
indent[len+1] = ' ';
(void) sprint f (temp, "%s/%s", path_name, child);
dump_defaults (temp, indent) ;
while (sibling = defaults_get_sibling(temp, NULL)
!= NULL) {
(void) sprintf (temp, "%s/%s", path_name,
sibling);
(dump_defaults(temp, indent);
}
}
main ()
{
char indent_buf [100] =
dump__defaults ("/", indent);
}
v_ *
10.5. Conversion Programs The defaults package provides a mechanism to convert from an existing customi¬
zation file, such as .mailrc, to the .d format used by def aultsedit.
You must write a separate program to do the conversion each way. Specify the
name of the program converting from the existing customization file to the
defaults format as the value of the $Specialf ormat_to_def ault s option
in the corresponding . d file. The program to go the other way is specified as
$Defaults_to_specialformat.
As an example, at Sun we have written programs to convert from the traditional
.mailrc file to the defaults format. The file
/usr/lib/defaults/Mail. d contains the lines:
/Mail
//$Specialformat_to_defaults "mailrc_to_defaults"
//$Defaults_to_specialformat "defaults_to_mailrc"
V microsystems
Revision A, of May 9, 1988
Chapter 10 — The User Defaults Database 155
If a program is specified as the value for $Specialf ormat_to_def aults,
then def aultsedit runs the program the first time it needs to display the
options for that category. When the user saves the changes she or he has made to
the database, and any changes that were made to the category, then the
$Defaults_to_specialf ormat program is run.
To write your own conversion programs, use the following guidelines. Read the
customization file into the program. Then, to go from the customization file to
.defaults, you simply figure out the appropriate option value to set, and set it
with the routine def ault s_set_string () . 30 To go the other way, retrieve
the value from the defaults database with the appropriate get routine, then make
the appropriate change to the customization file.
Note: Conversion programs should use the master database, regardless of the
setting of the def aultsedit option Private-only. To do this, call the function
def ault s_special_mode () as the first statement of your program.
10.6. Property Sheets Many window programs have property sheets that the end-user can use to modify
the behavior of their programs. You may use the defaults database to store the
information set by the user.
The following discussion uses code fragments taken from the default Jiler pro¬
gram printed at the end of this chapter.
The filer program has a property sheet that consists of one item, the flags to pass
through to the 1 s command. This property is represented as a string. When the
property sheet is popped up it is necessary to read the value from the database:
r --\
char *filer_flags;
filer_flags = defaults_get_string("/Filer/LsFlags", "-l”,
NULL);
v-—___,
When, the user changes the flags property, it is necessary to store the new value
into the database. This is done using
defaults_set_string(path_name, new_value, status).
For example:
f >
filer_flags = code from example;
defaults_set__string(”/Filer/LsFlags", filer_flags, NULL);
V_
30 defaults_set_string () is documented in <de fault s/defaults .h>.
Revision A, of May 9, 1988
156 Sun View 1 System Programmer’s Guide
10.7. Error Handling
Error Action
This code writes the new value into the defaults database in memory. The new
value will not be stored in the file system until the user pushes the Done button.
When this occurs, the routine defaults_write_changed (f ile_name,
status ) is called. This routine will write any database values in memory that
are different from the ones in the master database to the defaults file
f ile_name. If f ile_name has a value of NULL, then it will be written out to
the user’s private defaults database file. So,
-—— v
defaults_write_changed(NULL, NULL);
L_ J
will cause the defaults values to be stored to ~ /. default s.
If the user pushes the Reset button, then you want to reset the property sheet to
be the value that the property sheet had when it first came up. A call to
defaults_reread (path_name, status) will restore the database
under path_name from the file system. So,
-\
defaults_reread("/Filer", NULL);
V_ )
will restore the defaults database for the filer property sheet. You can obtain the
original value by reentering the property sheet display code to obtain the original
values.
The defaults routines report errors by printing messages on the standard error
stream stderr. The most common cause for getting error messages is that a
program that uses the defaults database is copied from somewhere without also
copying the associated master defaults database file. While these messages are
annoying, in general the program will continue to work, since every routine that
accesses the defaults database has a def ault_value argument that will be
returned if an option is not present in the database. 31
Using def ault sedit, the user can set two options for the defaults database
itself to control error reporting:
Error_Action controls what happens when an error is encountered. Possible
values are:
□ Continue: print an error message and continue execution.
□ Suppress: no action is taken.
□ Abort: print an error message and terminate execution on encountering the
first error.
Most users will want to set Error Action to either Continue or Suppress. Use
Suppress if you are getting all sorts of extraneous defaults error messages. Abort
is useful for forcing programmers to track down extraneous error messages prior
to releasing software to a larger community.
31 These error messages are not printed when Private_only is True.
microsystems
Revision A, of May 9, 1988
Chapter 10 — The User Defaults Database 157
MaximumErrors Maximum_Errors puts a limit on the number of error messages which will be
printed regardless of the setting of Error Action.
TestJAode The option TestJAode is provided to facilitate the testing of software prior to
release to a larger community. Use it to check for incorrect values for the
def ault_value argument to the get routines. When Test_Mode is set to
Enable, the defaults database is made inaccessible. In this mode, every time an
option value is accessed, a diagnostic message is generated and the value passed
in as def ault_value is returned.
Note that once enabled, TestJAode can not be disabled using def ault sedit.
This is one time when you must edit your . defaults file by hand, to set the
TestJAode option to Disabled (or remove the entry altogether).
10.8. Interface Summary The following table lists and explains all of the procedures that may be used to
make use of the defaults database.
Table 10-2 Default Procedures
Routine
Description
Bool
defaults_exists(path_name, status)
char *path_name;
int *status;
Returns TRUE if path_name exists in the
database.
Bool
defaults_get_boolean (option_name, default, 0)
char *option_name;
Bool default;
Looks up path_name in the database and returns
TRUE if the value is True, Yes,
On, Enabled, Set, Activated, or 1.
FALSE is returned if the value is False, No, Off,
Disabled, Reset, Cleared, Deactivated,
or 0. If the value is not one of the above values,
then a warning message is displayed and the default is
returned.
char
def ault s_get__character (opt ion_name, default, 0)
char *option_name;
char default;
Looks up path_name in the defaults
database and returns the resulting character value.
The default value is returned in an error occurs.
char *
default s_get_child (path_name, status)
char *path_name;
int *status;
Returns a pointer to the simple name associated with
the next sibling of path_name. NULL will be returned
if path_name does not exist or if path__name does
not have an next sibling
^sun
Revision A, of May 9,1988
158 Sun View 1 System Programmer’s Guide
Table 10-2 Default Procedures—Continued
Routine
Description
char *
defaults_get_default(path_name, default,
status)
Returns the value associated with path_name
char *path_name;
prior to being overridden by the clients private database.
char *default_value;
default is returned in any error occurs.
int *status;
int
Looks up the values associated with path_name, scans
defaults get enum(option name, pairs, 0)
the pairs table, and returns the associated value. If no
char *option name;
match can be found, then an error will be generated and
the value associated with the last entry will be returned.
Defaults^pairs *pairs;
(See default s_lookup ().)
int
defaults_get_integer (option_name, default, 0)
Looks up path_name in the defaults database
char *option_name;
and returns the resulting integer. The default value is
int default;
returned if any error occurs.
int
default s__ge t__i nt ege r_che ck (opt ion_name,
default_value.
Looks up path_name in the defaults database
min, max, 0)
and returns the resulting value. If the value
char *option_name;
in the database is not between minimum and
int default_value;
maximum (inclusive), then an error message will be
int min, max;
printed. The default will be returned if an error
occurs.
char *
defaults_get_sibling(path_name, status)
Returns a pointer to the simple name associated with the
char *path_name;
next sibling of path__name. NULL will be returned, if
int *status;
path_namedoes not exist or if path name does not
-
have an next sibling.
char *
Looks up path_name in the defaults database
defaults_get_string(option_name, default
, 0)
and returns the string value associated with it
char *option_name;
The default will be retuned if any error occurs.
char *default;
void
Rereads the portion of the database associated with
default s_reread (path__name, status)
path_jname.
char *path_name;
int * status;
defaults_set_character(path_name, value.
status)
Sets path_name to value, while value
char *path__name;
is a character.
char value;
int *status;
Revision A, of May 9,1988
Chapter 10 — The User Defaults Database 159
Table 10-2 Default Procedures—Continued
Routine
Description
void
defaults_
set_enumeration(path_name, value, status)
Sets path_name to value, where value
char
*path_name;
is a pointer to a string.
char
*value;
int
*status;
void
defaults
set__integer (path_name, value.
status)
Sets path_name to value, where value
char
*path_name;
is an integer.
int
value;
int
*status;
void
defaults
set string(path_name, value.
status)
Sets path_name to valuewhere value
char
*path_name;
is a pointer to a string
char
*value;
int
*status;
void
Causes the database to behave as if the entire master
default s_
_special_mode()
database has been read into memory prior to reading in
the private database. This is done to insure that the order
of nodes that default sedit presents is the same as
that in the . d files, regardless of what the user happens
to have set in his or her private database.
void
default s_
write__all (pathjname, file_name, status)
Writes out all of the data base nodes from
char
*path_name;
path_name and below into f ile_name. Out_f ile
char
*file_name;
is the string name of the file to create. If f ile_name is
int
*status;
NULL, then env var DEFAULTS_FILE will be used.
void
Writes out all of the private database entries to
default s_
char
int
_write__changed (file_name, status)
*file_name;
*status;
f ile_name. Any time a database node is set, it
becomes part of the private database. If the value of the
Filename is NULL, then DEFAULTS_FILE will be
used.
void
defaults_
_write_differences(file_name.
status)
Writes our all of the database entries that differ
char *file_name;
from the master database. Out_File is the string
int
*status;
name of the file to create. If f ile_name is NULL,
env var DEFAULTS_FI LE is used.
microsystems
Revision A, of May 9,1988
160 Sun View 1 System Programmer’s Guide
10.9. Example Program:
filer Defaults Version
The following program is a variation of the filer program discussed in the Sun-
View 1 Programmer’s Guide. It uses some of the defaults procedures discussed
in this chapter.
/*****************************************************************************/
/* 4.0 f iler_default. c */
/*****************************************************************************/
#include
♦include
♦include
♦include
♦include
♦include
♦include
♦include
< suntool/sunview.h>
<sunwindow/defaults.h>
<suntool/panel.h>
<suntool/tty.h>
<suntool/textsw.h>
<suntool/seln.h>
<suntool/alert.h>
<sys/stat.h> /* stat call needed to verify existence of files
*/
/* these objects are global so their attributes can be modified or retrieved */
Frame
Panel
Tty
Textsw
Panel_item
int
char *compose_ls_options () ;
base_frame, edit_frame, ls_f lags_f rame;
panel, ls_flags_panel;
ttysw;
editsw;
dir_item, fname_item, filing_mode_item, reset_item, done_item;
qu i t__conf i rmed_f rom_pane 1 ;
♦define MAX_F I LENAME_LEN 256
♦define MAX PATH LEN 1024
char *getwd();
main(argc, argv)
int argc;
char **argv;
{
static Notify_value filer_destroy_func();
void ls_flags_proc () ;
base_frame = window_create (NULL, FRAME,
FRAME_ARGS, argc, argv,
FRAME_LABEL, "filer",
FRAME_PROP S_ACT I ON_PROC, 1 s_f 1 ag s_pr oc,
FRAME_PROPS_ACTIVE, TRUE,
FRAME_NO_CONFIRM, TRUE,
0 );
(void) notify_interpose_destroy_func (base_frame, filer_destroy_func) ;
create_panel__subwindow () ;
create__tty_subwindow () ;
create_edit_popup () ;
create_ls_f lags_popup ();
quit__confirmed_f rom__panel = 0;
window_main_loop (base_frame) ;
exit(0);
m sun
\r microsystems
Revision A, of May 9, 1988
Chapter 10 — The User Defaults Database 161
create_tty_subwindow ()
{
ttysw = window__c reate (base_frame, TTY, 0);
}
create_edit_popup()
{
edit__frame = window__create (base_frame, FRAME,
FRAME_SHOW_LABEL, TRUE,
0 );
editsw = window_create (edit__f rame, TEXTSW, 0) ;
}
create_panel_subwindow()
{
void ls_proc () , ls_f lags_j)roc () , quit_proc () , edit_proc () ,
edit__sel_j?roc () , del_proc () ;
char current_dir [MAX_PATH_LEN] ;
panel = window_create (base_frame, PANEL, 0) ;
(void) panel_create_item(panel,
PANE L__LABE L_X,
PANE L_LABE L_Y,
PANEL_LABE L_IMAGE,
PANEL_NOTIFY_PROC,
0 );
PANEL_BUTTON,
ATTR_COL(0),
ATTR_ROW(0),
panel__button_image (panel, "List Directory",
ls_proc.
0 , 0 ),
(void) panel_create_item(panel,
PANE L_LABE L_IMAGE,
P ANEL_NOT I FY__PR0C,
0 );
PANEL_BUTTON,
panel_button_image(panel, "Set Is flags",
ls_flags_proc.
0 , 0 ),
(void) panel__create__item(panel,
PANEL_LABEL_IMAGE,
PANEL_NOTIFY_PROC,
0 );
PANEL_BUTTON,
panel_button_image (panel, "Edit",
edit_j?roc.
0 , 0 ),
(void) panel_create_item(panel,
PANEL_LABE L_IMAGE,
PANEL_NOTIFY_PROC,
0 );
PANEL_BUTTON,
panel_button_image(panel,
del_j?roc.
"Delete", 0, 0),
(void) panel_create_item(panel, PANEL_BUTTON,
PANEL_LABEL_IMAGE, panel_button_image(panel, "Quit", 0, 0),
PANEL_NOTIFY_PROC, quit_proc,
0 ) ;
f iling_mode__item = panel_c reate
PANE L_LABE L_X,
PANEL_LABEL_Y,
P ANEL_LABEL__STR ING,
PANEL_CHOICE_STRINGS,
0 );
item(panel, PANEL_CYCLE,
ATTR__C0L (0) ,
ATTR_ROW(l),
"Filing Mode:",
"Use \"File:\" item",
"Use Current Selection", 0,
(void) panel_create_item(panel, PANEL_MESSAGE,
<m sun
\r microsystems
Revision A, of May 9,1988
162 SunView 1 System Programmer’s Guide
PANEL LABEL X,
ATTR_C0L(0),
>
PANEL_LABEL_Y,
ATTR_R0W(2),
o
dir item * panel__create_item(panel.
PANEL_TEXT,
PANEL LABEL X,
ATTR_C0L(0),
PANEL LABEL_Y,
ATTR_R0W(3),
PANEL VALUE DISPLAY LENGTH,
60,
PANEL_VALUE,
getwd(current_dir),
PANEL LABEL_STRING,
"Directory: ",
0);
fname item = panel_create_item (panel, PANEL_TEXT,
PANEL LABEL X,
ATTR_C0L(0),
PANEL LABEL Y,
ATTR_R0W(4),
PANEL LABEL DISPLAY_LENGTH,
60,
PANEL_LABE L_STRING,
"File: ",
o
window_fit_height(panel);
}
window_set(panel, PANEL_CARET_ITEM,
fname__item, 0);
typedef struct Filer {
};
char *flags;
char *path;
struct Filer f iler__options = {" ",
r "/Filer/Options"};
struct Filer filer_format * {" 1 ",
"/Filer/Format"};
struct Filer filer_sort_order = {" ]
c ", "/Filer/Sort_0rder"};
struct Filer filer__sort_criterion =
{" tu", "/Filer/Sort_Criterion"};
struct Filer filer_directories = {"
d ", "/Filer/Sort_Directories"};
struct Filer filer_recursive = {" R
", "/Filer/Recursive"};
struct Filer filer_file_type = {" F
", "/Filer/File_Type"};
struct Filer filer_dot_files = {" a
", "/Filer/Dot_Files"};
create_ls flags_popup()
{
void done__proc () ;
void reset__proc ();
ls_flags_frame * window_create (base
_frame, FRAME, 0);
ls_flags_panel = window_create (ls_flags__f rame, PANEL, 0);
pane l_c re at e__i t e m (1 s_f lags_jpanel, PANE L_ME S S AGE,
PANEL_ITEM_X,
ATTR_C0L(14),
PANEL_ITEM_Y,
ATTR_ROW(0),
PANE L_LABEL_ST RING,
"Options for Is command".
PANE L_CL I ENT__D ATA,
&fi1er_options,
0);
panel_create_item(ls_flags_panel, PANEL_CYCLE,
P ANEL__I TEM_X,
ATTR__C0L (0) ,
P ANEL__I TEM_Y,
ATTR_R0W(1),
\ _
PANEL_D I SPLAY_LEVEL,
PANEL_CURRENT,
w sun Revision A, of May 9,1988
\r microsystems
Chapter 10 — The User Defaults Database 163
r
PANE L_LABE L_S T RIN G,
"Format:
A
PANEL_CHOICE_STRINGS,
"Short", "Long", 0,
PANEL CLIENT DATA,
&filer format.
o
panel_create_item(ls_flags_panel.
PANE L_CY CLE,
PANEL_ITEM_X,
ATTR_C0L(0),
P ANEL__I TEM_Y,
ATTR_R0W (2) ,
PANEL_DISPLAY_LEVEL,
PANEL_CURRENT,
PANEL_LABEL_STRING,
"Sort Order: ",
PANEL__CH01 CE_STRI NGS,
"Descending", "Ascending", 0,
PANEL CLIENT DATA,
0);
&filer sort order.
panel_create_item(ls_flags_panel.
PANE L_CY CLE,
P ANEL__I TEM_X,
ATTR__C0L (0) ,
PANEL_ITEM_Y,
ATTR_R0W(3),
PANEL_DISPLAY_LEVEL,
PANEL CURRENT,
PANEL__LABEL_STRING,
"Sort criterion: ",
PANEL_CHOICE_STRINGS,
"Name", "Modification Time",
"Access Time", 0,
PANEL CLIENT DATA,
&filer sort criterion.
o
panel_create_item(ls_flags_panel.
PANEL_CYCLE,
PANEL_ITEM_X,
ATTR_C0L(0),
PANEL_ITEM_Y,
ATTR_R0W(4),
PANEL_D IS P LA Y_LE VE L,
PANEL_CURRENT,
PANEL_LABEL_STRING,
"For directories, list: ",
PANEL_CHOICE_STRINGS,
"Contents", "Name Only", 0,
PANE L_CL I ENT__D ATA,
&filer_directories,
o
p an e l_c r e a t e__i t e m (1 s_f 1 a g s__pa n e 1,
PANEL_CYCLE,
PANEL_ITEM_X,
ATTR_C0L(0) ,
P ANEL_I TEM__Y,
ATTR_R0W(5),
PANELJDISPLAY_LEVEL,
PANEL_CURRENT,
PANEL_LABEL_STRING,
"Recursively list subdirectories? ",
PANEL_CHOICE_STRINGS,
"No", "Yes", 0,
PANEL CLIENT DATA,
0);
&filer_recursive.
panel_create_item(ls__flags_jpanel.
PANE L__C Y CLE,
PANEL_ITEM_X,
ATTR_COL(0),
P ANEL_I TEM__Y,
ATTR_R0W(6),
PANEL_DISPLAY_LEVEL,
PANEL_CURRENT,
PANEL_LABEL_STRING,
"List files?
PANE L_CH01CE_STRINGS,
"No", "Yes", 0,
PANEL CLIENT DATA,
0);
& f i 1 e r__do t_f i 1 e s,
panel_create_item(ls_flags_panel.
PANE L_C Y CLE,
PANEL_ITEM_X,
ATTR_C0L(0),
PANEL__ITEM_Y,
ATTRJR0W(6),
P ANEL_D I SPLAY_LEVEL,
PANEL_CURRENT,
PANEL__LABEL_STRING,
"Indicate type of file? ",
PANEL_CHOICE_STRINGS,
"No", "Yes", 0,
PANEL_CLI ENT_DATA,
&filer_file_type.
sun Revision A, of May 9, 1988
microsystems
164 SunView 1 System Programmer’s Guide
0 );
done_item =* panel_create_item (ls_f lags_panel, PANEL__BUTTON,
PANEL__I TEM_X, ATTR_COL (1) ,
P ANEL_I TEM_Y , ATTR_ROW (8) ,
PANEL_LABEL__IMAGE, panel_button_image (panel,
PANE L_N OTIF Y_P ROC, done_j?roc,
0 );
"Done", 6, 0) ,
reset_item = panel_create_item (ls_f lags_panel, PANEL_BUTTON,
PANEL__I TEM_X, ATTR__COL (12),
PANEL_LABEL_IMAGE, panel_button_image(panel, "Reset", 6, 0),
PANE L_N OTIFY_PROC, re set_proc,
0 );
}
(void)compose_ls_options (1);
window_fit(ls_f lags_j?anel); /*
window_fit(ls_flags_frame); /*
fit panel around its items */
fit frame around its panel */
char *
compose_ls_options (control)
int control;
{
static char
char
char
int
Panel_item
struct Filer
int
flags[20];
*ptr;
flag;
first_flag =
item;
*client_data;
index;
TRUE;
ptr = flags;
panel_each_item (ls__flags_panel, item)
if ((item != done_item) && (item != reset_item)) {
client_data = (struct Filer *)panel_get(item,
PANEL__CLIENT_DATA, 0) ;
switch (control) {
case 0:
index = (int) panel_get__value (item) ;
defaults_set_integer((char *)client_data->path,
(int)index, (int *)NULL);
break;
case Is
index = defaults_get__integer((char *)client_data->path,
(int)1, NULL);
panel_set__value (item, index) ;
break;
case 2:
flag = client_data->flags[index];
if (flag !=''){
if (first_flag) {
*ptr++ = ' ;
first_flag = FALSE;
}
*ptr++ = flag;
}
}
m sun
\r microsystems
Revision A, of May 9, 1988
Chapter 10 — The User Defaults Database 165
}
panel_end_each
*ptr - 'Non¬
return flags;
}
void
ls_j?roc ()
{ "
static char previous_dir [MAX_PATH_LEN] ;
char *current_dir;
char cmdstring[100]; /* dir_item's value can be 80, plus flags */
current_dir = (char *)panel_get_value(dir_itern);
if (strcmp(current_dir, previous_dir)) {
chdir((char *)panel_get_value(dir_item));
strcpy (previous__dir, current_dir) ;
}
sprintf(cmdstring, "Is %s %s/%s\n",
compose_ls_options(),
current_dir,
panel_get_value(fname_item));
ttysw__input (ttysw, cmdstring, strlen (cmdstring) ) ;
}
void
ls__f lags_j?roc ()
{ "
window_set (ls_flags_f rame, WIN__SHOW, TRUE, 0) ;
}
void
done_proc ()
{
window_set (ls_flags__frame, WIN_SHOW, FALSE, 0) ;
(void) compose_ls__options (0);
defaults_writexchanged(NULL, NULL);
}
void
reset_proc ()
{
defaults__reread ("/Filer" , NULL) ;
}
/* return a pointer to the current selection */
char *
get_selection ()
{
static char filename[MAX_FILENAME_LEN];
Seln_holder holder;
Seln_request *buffer;
holder = seln_inquire (SE LN__PR I MARY) ;
buffer = seln_ask(^holder, SELN_REQ_CONTENTS_ASCII, 0, 0);
strncpy(
filename, buffer->data + sizeof(Seln_attribute), MAX_FILENAME_LEN);
m sun
\r microsystems
Revision A, of May 9, 1988
166 SunView 1 System Programmer’s Guide
return (filename) ;
}
/* return 1 if file exists, else print error message and return 0 */
stat__file (filename)
char *filename;
{
static char previous_dir[MAX_PATH_LEN];
char *current_dir;
char this_f ile [MAX_PATH_LEN] ;
struct stat statbuf;
current_dir = (char *)panel_get_value(dir_item);
if (strcmp(current_dir, previous_dir)) {
chdir((char *)panel_get_value(dir_item));
strcpy(previous_dir, current_dir);
}
sprintf (this_f ile, "%s/%s", current_dir, filename);
if (stat(this_file, Sstatbuf) < 0) {
char buf[MAX_FILENAME_LEN+11]; /* big enough for message */
sprintf(buf, "%s not found.", this_file);
msg(buf, 1);
return 0;
}
return 1;
}
void
edit^proc ()
{
void edit_f ile_jproc () , edit_sel_proc () ;
int file_mode = (int) panel_get_value (f iling__mode_item) ;
if (file_mode) {
(void)edit_sel_proc();
} else {
(void)edit_file_proc ();
}
}
void
edit_file__proc ()
{
char *filename;
/* return if no selection */
if (!strlen(filename = (char *)panel_get_value(fname_item))) {
msg("Please enter a value for \"File:\".", 1);
return;
}
/* return if file not found */
if (!stat_file(filename))
return;
window_set(editsw, TEXTSW_FILE, filename, 0);
W sun
xr microsystems
Revision A, of May 9, 1988
Chapter 10 — The User Defaults Database 167
window_set(edit_jframe, FRAME_LABEL, filename, WIN_SHOW, TRUE, 0);
}
void
edit_sel_j?roc ()
{
char *filename;
/* return if no selection */
if (! strlen (filename * get__selection () ) ) {
msg("Please select a file to edit.", 0);
return;
}
/* return if file not found */
if (!stat_file(filename))
return;
window_set (editsw, TEXTSW__FILE, filename, 0);
window_set(edit_frame, FRAME_LABEL, filename, WIN_SH0W, TRUE, 0);
}
void
del_jproc ()
{
char buf[300];
char *filename;
int result;
Event event; /* unused */
int file_mode = (int) panel_get_value (f iling_mode_item) ;
/* return if no selection */
if (file_mode) {
if (!strlen(filename = get_selection())) {
msg("Please select a file to delete.", 1);
return;
}
} else {
if (! strlen (filename = (char *) panel_get_value (fname__item) ) ) {
msg("Please enter a file name to delete.", 1);
return;
}
}
/* return if file not found */
if (!stat_file(filename))
return;
/* user must confirm the delete */
result = alert_j5rompt(base_frame, &event,
ALERT_MESSAGE_STRINGS,
"Ok to delete file:",
filename,
0,
ALERT_BUTTON_YES, "Confirm, delete file",
ALERT_BUTT0N_N0, "Cancel",
0);
w su , n
Xr microsystems
Revision A, of May 9, 1988
168 Sun View 1 System Programmer’s Guide
switch (result) {
case ALERT_YES:
unlink(filename) ;
sprintf(buf, "%s deleted.", filename);
msg(buf, 0);
break;
case ALERT_NO:
break;
case ALERT__FAILED: /* not likely to happen unless out of FDs */
printf("Alert failed, will not delete %s.\n", filename);
break;
■' )
}
int
confirm_quit()
{
int result;
Event event; /* unused */
char *msg = "Are you sure you want to Quit?";
result = alert_prompt(base_frame, &event,
ALERT_MESSAGE_STRINGS,
"Are you sure you want to Quit?",
0,
ALERT JBUTTON_YES, "Confirm" ,
ALERT_BUTT 0N_N 0, "Cancel",
0 );
switch (result) {
case ALERT_YES:
break;
case ALERT_N0:
return 0;
case ALERT_FAILED: /* not likely to happen unless out of FDs */
printf("Alert failed, quitting anyway.\n");
break;
}
return 1;
}
static Notify_value
filer_destroy__func (client, status)
Notify__client client;
Destroy_status status;
{
if (status == DE S TROY_CHECKING) {
if (quit_confirmed_f rom_j>anel) {
return (notify_next_destroy__func (client, status) ) ;
} else if (confirm_quit () === 0) {
(void) notify__veto_destroy ( (Notify_client) (LINT__CAST (client) ) ) ;
return(N0TIFY_D0NE);
}
}
return(notify_next_destroy_func(client, status));
}
void
quit_proc ()
W sun
\r microsystems
Revision A, of May 9, 1988
Chapter 10 — The User Defaults Database 1 69
{
if (confirm_quit()) {
quit__confirmed_f rom_panel = 1;
window_destroy (base_frame) ;
}
}
msg(msg, beep)
char *msg;
int beep;
{
char buf[300];
int result;
Event event; /* unused */
char *contine_msg = "Press \"Continue\" to proceed.";
result = alert^prompt(base_frame, Sevent,
ALERT_MESSAGE__STRINGS,
msg,
contine_msg,
0,
ALERT_NOJBEEPING, (beep) ? 0:1,
ALERT_BUTTON_YES, "Continue",
ALERT_TRIGGER, ACTI0N_ST0P, /* allow either YES or NO answer */
0 );
switch (result) {
case ALERT_YES:
case ALERT_TRIGGERED: /* result of ACTION_STOP trigger */
break;
case ALERT_FAILED: /* not likely to happen unless out of FDs */
printf("Alert failed, continuing anyway.\n");
break;
}
}
microsystems
Revision A, of May 9,1988
Advanced Imaging
Advanced Imaging. 173
11.1. Handling Fixup. 173
11.2. Icons. 174
Loading Icons Dynamically. 174
Icon File Format. 174
11.3. Damage. 176
Handling a SIGWINCH Signal. 176
Image Fixup. 176
11.4. Pixwin Offset Control. 178
Advanced Imaging
11.1.
Handling Fixup
The chapter covers some topics on low level image maintenance. There is also a
section on icon manipulation.
The routines pw_read (), pw_copy () and pw_get () may find themselves
thwarted by trying to read from a portion of the pixwin which is hidden, and
therefore has no pixels. This can happen with a canvas that you have made non-
retained. When this happens, pw_fixup (a struct rectlist) in the
pixwin structure will be filled in by the system with the description of the
source areas which could not be accessed. The client must then regenerate this
part of the image into the destination. Retained pixwins will always return
rl_null in pw_f ixup because the image is refreshed from the retained
memory pixrect.
The usual strategy when calling pw_copy () is to call the following routine to
restrict the pixwin’s clipping to just that part of the image that needs to be fixed
up.
pw_restrict_clipping(pw, rl)
Pixwin *pw;
Rectlist *rl;
You pass in &pw->pw_fixup as rl. Now you draw your entire pixwin. Only
the parts that need to be repaired are drawn. Now you need to reset your pixwin
so that you may access its entire visible surface.
pw_exposed(pw)
Pixwin *pw;
pw_exposed () is the call that does this.
Dealing with fixup for pw_read () or pw_get () is really quite ludicrous.
One should really run these retained if they are using the screen as a storage
medium for their bits.
microsystems
173
Revision A, of May 9, 1988
174 Sun View 1 System Programmer’s Guide
11.2. Icons
Loading Icons Dynamically
Icon File Format
The basic usage of icons is described in the Icons chapter of the SunView
Programmer s Guide. The opaque type Icon, and the functions and attributes
by which icons are manipulated, are defined in the header file
<suntool/icon.h>.
Applications such as icon editors or browsers, which need to load icon images at
run time, will need to use the functions described in this section. The definitions
necessary to use these functions are contained in <suntool/icon_load. h>.
You can load an icon’s image from a file with the call:
int
icon_load(icon, file, error_msg)
Icon icon;
char *file, *error_msg;
Icon is an icon returned by icon_create (); file is the name of a file
created with iconedit. error_msg is the address of a buffer (at least 256 char¬
acters long) into which icon_load () will write a message in the event of an
error. If icon_load () succeeds, it returns zero; otherwise it returns 1.
The function
int
icon_init_from_pr(icon, pr)
Icon icon;
Pixrect *pr;
initializes the width and height of the icon’s graphics area (attribute
ICON_IMAGE_RECT) to match the width and height of pr. It also initializes
the icon’s label (attribute ICON_LABEL) to NULL. The return value is meaning¬
less.
To load an image from a file into a pixrect, use the routine:
Pixrect *
icon_load_mpr(file, error_msg)
char *file, *error_msg;
This function allocates a pixrect, and loads it with the image contained in file.
If no problem is encountered, icon_load_mpr () returns a pointer to the new
pixrect containing the image. If it can’t access or interpret the file,
icon_load_mpr () writes a message into the buffer pointed to by
error_msg and returns NULL.
iconedit writes out an ASCII file consisting of two parts: a comment describing
the image, and a list of hexadecimal constants defining the actual pixel values of
the image. The contents of the file <images/template. icon> are repro¬
duced below, as an example:
msun
microsystems
Revision A, of May 9, 1988
Chapter 11 — Advanced Imaging 175
/* Format_version=l, Width=16, Height=16, Depth=l, Valid_bits_per_item=16
* This file is the template for all images in the cursor/icon library.
* The first line contains the information needed to properly interpret
* the actual bits, which are expected to be used directly by software
* that wants to do compile-time binding to an image via a #include.
* The actual bits must be specified in hex.
* The default interpretation of the bits below is specified by the
* behavior of mpr_static.
* Note that Valid_bits_per_item uses the least-significant bits.
* See also: icon_load.h.
* Description: A cursor that spells "TEMPLATE” using two lines, with a
* solid bar at the bottom.
* Background: White
*/
0xED2F, 0x49E9, 0x4D2F, 0x4928, 0x4D28, 0x0000, 0x0000, 0x8676,
0x8924, 0x8F26, 0x8924, 0xE926, 0x0000, 0x0000, OxFFFF, OxFFFF
The first line of the comment is composed of header parameters, used by the icon
loading routines to properly interpret the actual bits of the image. The
f ormat_ver sion exists to permit further development of the file format in a
compatible manner, and should always be 1. Default values for the other header
parameters are Depth=l, Width=64, Height=64,
Valid_bits_per__item=16.
The remainder of the comment can be used for arbitrary descriptive material.
The following function is provided to allow you to preserve this material when
rewriting an image file:
FILE *
icon__open__header (f ile, error_msg, info)
char *file, *error_msg;
icon header handle info;
typedef struct icon_header_object {
int depth,
height,
format_version,
valid_bits_per_item,
width;
long last_j?aram_j?os;
} icon_header_object;
icon_open_header fills in info from file's header parameters,
inf o->last_param_pos is filled in with the position immediately after the
last header parameter that was read. The FILE * returned by
icon_open_header () is left positioned at the end of the header comment.
Thus f tell (icon_open_header () ) indicates where the actual bits of the
image should begin, and the characters in the range
[info->last_param_pos...ftell(icon_open_header()]
encompass all of the extra descriptive material contained in the file’s header.
Nr microsystems
Revision A, of May 9,1988
176 Sun View 1 System Programmer’s Guide
11.3. Damage
Handling a SIGWINCH
Signal
Image Fixup
This section is included for those who can’t use the Agent to hide all this com¬
plexity. Try to use the Agent, because it is very hard to get the following right.
When a portion of a client’s window becomes visible after having been hidden, it
is damaged. This may arise from several causes. For instance, an overlaying
window may have been removed, or the client’s window may have been
stretched to give it more area. The client is notified that such a region exists
either by the events WIN_REPAINT or WIN_RES IZE, or if the client is not
using the Notifier, by the signal SIGWINCH; this simply indicates that something
about the window has changed in a fashion that probably requires repainting. It
is possible that the window has shrunk, and no repainting of the image is required
at all, but this is a degenerate case. It is then the client’s responsibility to repair
the damage by painting the appropriate pixels into that area. The following sec¬
tion describes how to do that.
There are several stages to handling a SIGWINCH. First, in almost all cases, the
procedure that catches the signal should not immediately try to repair the damage
indicated by the signal. Since the signal is a software interrupt, it may easily
arrive at an inconvenient time, halfway through a window’s repaint for some nor¬
mal cause, for instance. Consequently, the appropriate action in the signal
handler is usually to set a flag which will be tested elsewhere. Conveniently, a
SIGWINCH is like any other signal; it will break a process out of a select(2)
system call, so it is possible to awaken a client that was blocked, and with a little
investigation, discover the cause of the SIGWINCH.
Once a process has discovered that a SIGWINCH has occurred and arrived at a
state where it’s safe to do something about it, it must determine exactly what has
changed, and respond appropriately. There are two general possibilities: the
window may have changed size, and/or a portion of it may have been uncovered.
win_getsize () (described in Windows) can be used to inquire the current
dimensions of a window. The previous size must have been remembered, for
instance from when the window was created or last adjusted. These two sizes are
compared to see if the size has changed. Upon noticing that its size has changed,
a window containing other windows may wish to rearrange the enclosed win¬
dows, for example, by expanding one or more windows to fill a newly opened
space.
NOTE If you are using window_main_loop () to drive your program, then the
SIGWINCH is translated into a WIN_RESIZE and/or WIN_REP AINT event for
you. The rest of this discussion still applies.
Whether a size change occurred or not, the actual images on the screen must be
fixed up. It is possible to simply repaint the whole window at this point — that
will certainly repair any damaged areas — but this is often a bad idea because it
typically does much more work than necessary.
Therefore, the window should retrieve the description of the damaged area, repair
that damage, and inform the system that it has done so: The pw_damaged ()
procedure:
Revision A, of May 9,1988
Chapter 11 — Advanced Imaging 177
pw_damaged(pw)
Pixwin *pw;
is a procedure much like pw__exposed (). It fills in pwcd_clipping with a
rect list describing the area of interest, stores the id of that rectlist in the
pixwin’s pw_opshandle and in pwcd_damagedid as well. It also stores its
own address in pwco_getclipping, so that a subsequent lock will check the
correct rectlist. All the clippers are set up too. Colormap segment offset
initialization is done, as described in Surface Preparation.
CAUTION A call to pw_damaged () should ALWAYS be made in a sigwinch handling
routine. Likewise, pw_donedamaged () should ALWAYS be called before
returning from the sigwinch handling routine. While a program that runs
on monochrome displays may appear to function correctly if this advice is
not followed, running such a program on a color display will produce pecu¬
liarities in color appearance.
Now is the time for the client to repaint its window — or at least those portions
covered by the damaged rectlist; if the regeneration is relatively expensive,
that is if the window is large, or its contents complicated, it may be worth res¬
tricting the amount of repainting before the clipping that the rectlist will
enforce. This means stepping through the rectangles of the rectlist, deter¬
mining for each what data contributed to its portion of the image, and recon¬
structing only that portion. See the chapter on rectlists for details about rectlists.
For retained pixwins, the following call can be used to copy the image from the
backup pixrect to the screen:
pw_repairretained(pw)
Pixwin *pw;
When the image is repaired, the client should inform the window system with a
call to:
pw_donedamaged(pw)
Pixwin *pw;
pw_donedamaged () allows the system to discard the rectlist describing
this damage. It is possible that more damage will have accumulated by this time,
and even that some areas will be repainted more than once, but that will be rare.
After calling pw_donedamaged (), the pixwin describes the entire visible area
of the window.
A process which owns more than one window can receive a SIGWINCH for any
of them, with no indication of which window generated it. The only solution is
to fix up all windows. Fortunately, that should not be overly expensive, as only
the appropriate damaged areas are returned by pw_damaged ().
Revision A, of May 9,1988
178 SunView 1 System Programmer’s Guide
11.4. Pixwin Offset Control The following routines control the offset of a pixwin’s coordinate space. They
can be used for writing in a fixed coordinate space even though the pixwin moves
about relative to the window’s origin.
void
pw_set_x_offset(pw, offset)
Pixwin *pw;
int offset;
void
pw_set_y_offset(pw, offset)
Pixwin *pw;
int offset;
void
pw_set_xy_offset (pw, int x__offset, y_offset)
Pixwin *pw;
int x_offset, y_offset;
int
pw__get_x_of f set (pw)
Pixwin *pw;
int
pw_get_y_of f set (pw)
Pixwin *pw;
^§un
Revision A, of May 9, 1988
Menus & Prompts
Menus & Prompts
12.1. Full Screen Access. 181
Initializing Fullscreen Mode. 182
Releasing Fullscreen Mode. 182
Seizing All Inputs. 1 g 2
Grabbing I/O. 182
Releasing I/O. 182
12.2. Surface Preparation. 182
Multiple Plane Groups. 183
Pixel Caching. 183
Saving Screen Pixels. 183
Restoring Screen Pixels. 1 84
Fullscreen Drawing Operations. 184
Menus & Prompts
u
.1. Full Screen Access
This chapter describes routines that you will probably need when writing a menu
or prompt package of your own. Note, however, that SunView’s menu and alert
facilities documented in the SunView 1 Programmer’s Guide are both
comprehensive full-featured packages that handle fullscreen access for you. Also
note that you can use window_loop () together with one of the SunView win¬
dow types to create other kinds of full-screen prompts, again without having to
manage fullscreen interaction yourself.
To provide certain kinds of feedback to the user, it may be necessary to violate
window boundaries. Pop-up menus, prompts and window management are
examples of the kind of operations that do this. Th t fullscreen interface provides
a mechanism for gaining access to the entire screen in a safe way. The package
provides a convenient interface to underlying sunwindow primitives. The fol¬
lowing structure is defined in <suntool/f ullscreen. h>:
struct fullscreen {
int
fs_windowf di¬
struct
rect f s__screenrect ;
struct
pixwin *fs_pixwin;
struct
cursor fs__cachedcursor;
struct
inputmask fs_cachedim; /* Pick mask */
int
fs_cachedinputnext;
struct
inputmask fs__cachedkbdim; /* Kbd mask */
} ;
f s_windowf d is the window that created the fullscreen object,
f s_screenrect describes the entire screen’s dimensions, f s_pixwin is
used to access the screen via the pixwin interface. The coordinate space of
fullscreen access is the same as f s_windowfd’s. Thus, pixwin accesses are
not necessarily done in the screen’s coordinate space. Also, f s_screenrect
is in the window’s coordinate space. If, for example, the screen is 1024 pixels
wide and 800 pixels high, f s_windowfd has its left edge at 300 and its top
edge at 200, that is, both relative to the screen’s upper left-hand comer, then
f s_screenrect is {-300, -200, 1024, 800}.
The original cursor, f s_cachedcursor, input mask, f s_cachedim, and the
window number of the input redirection window, f s_cachedinputnext, are
cached and later restored when the fullscreen access object is destroyed.
A
microsystems
181
Revision A, of May 9, 1988
182 Sun View 1 System Programmer’s Guide
Initializing Fullscreen Mode
struct fullscreen *
fullscreen init(windowfd)
int windowfd;
gains full screen access for windowfd and caches the window state that is likely
to be changed during the lifetime of the fullscreen object, windowfd is set to
do blocking I/O. A pointer to this object is returned.
During the time that the full screen is being accessed, no other processes can
access the screen, and all user input is directed to f s->f s_windowfd.
Because of this, use fullscreen access infrequently and for only short periods of
time.
Releasing Fullscreen Mode
fullscreen_destroy(fs)
struct fullscreen *fs;
fullscreen destroy () restores f s’s cached data, releases the right to
access the full screen and destroys the fullscreen data object,
f s->f s windowf d’s input blocking status is returned to its original state.
Seizing All Inputs
Fullscreen access is built out of the grab I/O mechanism described here. This
lower level is useful if you wanted to only grab input.
Normally, input events are directed to the window which underlies the cursor at
the time the event occurs (or the window with the keyboard focus, if you have
split pick/keyboard focus). Two procedures modify this state of affairs.
Grabbing I/O
A window may temporarily seize all inputs by calling:
win_grabio(windowfd)
int windowfd;
The caller’s input mask still applies, but it receives input events from the whole
screen; no window other than the one identified by windowfd will be offered an
input event or allowed to write on the screen after this call.
Releasing I/O
win_releaseio(windowfd)
int windowfd;
undoes the effect of a win_grabio (), restoring the previous state.
12.2. Surface Preparation
In order for a client to ignore the offset of his colormap segment the image of the
pixwin must be initialized to the value of the offset. This surface preparation is
done automatically by pixwins under the following circumstances:
o The routine pw damaged () does surface preparation on the area of the
pixwin that is damaged.
□ The routine pw_put colormap () does surface preparation over the entire
exposed portion of a pixwin if a new colormap segment is being loaded for
the first time.
For monochrome displays, nothing is done during surface preparation. For color
displays, when the surface is prepared, the low order bits (colormap segment size
V microsystems
Revision A, of May 9, 1988
Chapter 12 — Menus & Prompts 183
Multiple Plane Groups
Pixel Caching
Saving Screen Pixels
minus 1) are not modified. This means that surface preparation does not clear the
image. Initialization of the image (often clearing) is still the responsibility of
client code.
There is a case in which surface preparation must be done explicitly by client
code. When window boundaries are knowingly violated, as in the case of pop-up
menus, the following procedure must be called to prepare each rectangle on the
screen that is to be written upon:
pw_preparesurface(pw, rect)
Pixwin *pw;
Rect *rect;
rect is relative to pw’s coordinate system. Most commonly, a saved copy of
the area to be written is made so that it can be restored later — see the next sec¬
tion.
On machines with multiple plane groups (such as the Sun-3/110 and other
machines using the cgf our(4S) frame buffer), pw_preparesurf ace () will
correctly set up the enable plane so that the rect you are drawing in is visible.
If you do not use pw_preparesurf ace (), it is possible that part of the area
you are drawing on is displaying values from another plane group, so that part of
your image will be occluded.
If your application violates window boundaries to put up fullscren menus and
prompts, it is often desirable to remember the state of the screen before you drew
on it and then repair it when you are finished. On machines with multiple plane
groups such as the Sun-3/110 you need to restore the state of the enable plane
and the bits in the other plane group(s). There are routines to help you do this.
This routine saves the screen image where you area about to draw:
Pw_pixel_cache *
pw_save__pixels (pw, rect) ;
Pixwin *pw;
Rect *rect;
typedef struct pw_pixel_cache {
Rect rect;
struct pixrect * plane_group[PIX_MAX_PLANE_GROUPS] ;
} Pw_pixel_cache;
pw_save_pixels () tries to allocate memory to store the contents of the pix¬
els in rect. If it is unable to, it prints out a message on stderr and returns
PW_PIXEL_CACHE_NULL. If it succeeds, it returns a pointer to a structure
which holds the rect rect and an array of pixrects with the values of the pixels
in rect in each plane group.
microsystems
Revision A, of May 9,1988
184 SunView 1 System Programmer’s Guide
Restoring Screen Pixels Then, when you have finished fullscreen access, you restore the image which you
drew over with:
void
pw_restore_j?ixels (pw, pc) ;
Pixwin *pw;
Pw_pixel__cache *pc;
pw_restore_pixels () restores the state of the screen where you drew. All
the information it needs is in the Pw_pixel_cache pointer that
pw_save_j?ixels () returned.
Fullscreen Drawing If you use pw_preparesurf ace (), you will be given a homogeneous area
Operations on which to draw during fullscreen access. However, for applications such as
adjusting the size of windows (“rubber-banding”), you do not want to obscure
what is underneath. On the other hand, on a machine with multiple plane groups
you want your fullscreen access to be visible no matter what plane groups are
being displayed.
The following routines perform the same vector drawing, raster operation and
pixwin copying as their counterparts in Imaging Facilities: Pixwins in the Sun-
View 1 Programmer’s Guide. The difference is that these routines guarantee that
the operation will happen in all plane groups so it will definitely be visible on¬
screen.
CAUTION To save a lot of overhead, these routines make certain assumptions which
must be followed.
Anyone calling these f ullscreen_pw_* routines must
o have called f ullscreen__init ()
□ have not done any surface preparation under the pixels affected
□ have not called pw_lock ()
□ use the fullscreen pixwin during this call
□ use a PIX_NOT (PIX_DST) operation.
void
f ullscreen__pw_vector (pw, xO
Pixwin *pw;
int xO, yO, xl, yl,
void
fullscreen_pw_write(pw, xw.
pr, xr.
Pixwin
*pw;
int
xw, yw, width.
Pixrect
*pr;
yO, xl, yl, op, value);
op, value;
yw, width, height, op,
yr) ;
height, op, xr, yr;
Revision A, of May 9,1988
Chapter 12 — Menus & Prompts 185
void
fullscreen_pw_copy(pw, xw, yw, width, height, op,
pw_src, xr, yr);
Pixwin *pw, *pw_src;
int xw, yw, width, height, op, xr, yr;
microsystems
Revision A, of May 9, 1988
Window Management
Window Management. 189
Tool Invocation. 190
Utilities . 190
13.1. Minimal Repaint Support. 192
13
Window Management
The window management routines provide the standard user interface presented
by tool windows:
wmgr_open(framefd, rootfd)
wmgr_close(framefd, rootfd)
wmgr_move(framefd)
wmgr_stretch(framefd)
wmgr__top (f ramefd, rootfd)
wmgr_bottom (framefd, rootfd)
wmgr_refreshwindow(windowfd)
wmgr__open () opens a frame window from its iconic state to normal size.
wmgr_close () closes a frame window from its normal size to its iconic size.
wmgr_move () prompts the user to move a frame window or cancel the opera¬
tion. If confirmed, the rest of the move interaction, including dragging the win¬
dow and moving the bits on the screen, is done. wmgr_stretch () is like
wmgr_move (), but it stretches the window instead of moving it.
wmgr_top () places a frame window on the top of the window stack.
wmgr_bottom () places the frame window on the bottom of the window stack.
wmgr_ref reshwindow () causes windowf d and all its descendant windows
to repaint.
The routine wmgr_changerect ():
wmgr_changerect(feedbackfd, windowfd, event, move, noprompt)
int feedbackfd, windowfd;
Event *event;
int move, noprompt;
implements wmgr_move () and wmgr_stretch (), including the user
interaction sequence, windowf d is moved (1) or stretched (0) depending on the
value of move. To accomplish the user interaction, the input event is read from
the feedbackfd window (usually the same as windowfd). The prompt is
turned off if noprompt is 1.
189
Revision A, of May 9, 1988
190 SunView 1 System Programmer’s Guide
Tool Invocation
Utilities
int
wmgr_confirm(windowfd, text)
int windowfd;
char *text;
wmgr_conf irm () implements a layer over the prompt package for a standard
confirmation user interface, text is put up in a prompt box. If the user
confirms with a left mouse button press, then —1 is returned. Otherwise, 0 is
returned. The up button event is not consumed.
NOTE This routine is preserved only for backwards compatibility with versions of the
SunOS prior to Release 4.0. You should use the new package documented in the
SunView 1 Programmer’s Guide for dialogs with the user. wmgr_conf irm ()
is not used for user interaction by SunView 1 packages unless the user has dis¬
abled Alerts in the Compatibility category of defaultsedit(l).
wmgr_forktool(programname, otherargs, rectnormal, recticon,
iconic)
char *programname, *otherargs;
Rect *rectnormal, *recticon;
int iconic;
is used to fork a new tool that has its normal rectangle set to rectnormal and
its icon rectangle set to recticon. If iconic is not zero, the tool is created
iconic, programname is the name of the file that is to be run and otherargs
is the command line that you want to pass to the tool. A path search is done to
locate the file. Arguments that have embedded white space should be enclosed
by double quotes.
The utilities described here are some of the low level routines that are used to
implement the higher level routines. They may be used to put together a window
.management user interface different from that provided by tools. If a series of
calls is to be made to procedures that manipulate the window tree, the whole
sequence should be bracketed by win_lockdata () and
win_unlockdata (), as described in The Window Hierarchy.
wmgr_completechangerect(windowfd, rectnew, rectoriginal,
parentprleft, parentprtop)
int windowfd;
Rect *rectnew, *rectoriginal;
int parentprleft, parentprtop;
does the work involved with changing the position or size of a window’s rect.
This involves saving as many bits as possible by copying them on the screen so
they don’t have to be recomputed. wmgr_completechangerect () would
be called after some programmatic or user action determined the new window
position and size in pixels, windowfd is the window being changed,
rectnew is the window’s new rectangle, rectoriginal is the window’s
original rectangle, parentprleft and parentprtop are the upper-left
screen coordinates of the parent of windowfd.
Revision A, of May 9,1988
Chapter 13 — Window Management 191
wmgr_winandchildrenexposed(pixwin, rl)
Pixwin *pixwin;
Rectlist *rl;
computes the visible portion of pixwin—>pw_clipdat a. pwcd_windowf d
and its descendants and stores it in rl. This is done by any window manage¬
ment routine that is going to try to preserve bits across window changes. For
example, wmgr_completechangerect () calls
wmgr_winandchildrenexposed ( ) before and after changing the window
size/position. The intersection of the two rectlists from the two calls are those
bits that could possibly be saved.
wmgr_changelevel(windowfd, parentfd, top)
int windowfd, parentfd;
bool top;
moves a window to the top or bottom of the heap of windows that are descen¬
dants of its parent, windowfd identifies the window to be moved; parentfd
is the file descriptor of that window’s parent, and top controls whether the win¬
dow goes to the top (TRUE) or bottom (FALSE). Unlike wmgr_top () and
wmgr_bottom ( ), no optimization is performed to reduce the amount of
repainting. wmgr_changelevel () is used in conjunction with other window
rearrangements, which make repainting unlikely. For example,
wmgr_close () puts the window at the bottom of the window stack after
changing its state.
tdefine WMGR_ICONIC WUF_WMGR1
wmgr_iswindowopen(windowfd)
int windowfd;
The user data of windowfd reflects the state of the window via the
WMGR_ICONIC flag. WUF_WMGR1 is defined in <sunwindow/win_ioctl.h> and
WMGR_ICONIC is defined in <suntool/wmgr.h> . wmgr_iswindowopen ()
tests the WMGR_ICONIC flag and returns TRUE or FALSE as the window is
open or closed.
Note that client programs should never set or clear the WMGR_ICONIC flag.
The rootf d window maintains a “next slot” position for both normal tool win¬
dows and icon windows in its unused iconic rect data.
wmgr_setrectalloc () stores the next slot data and
wmgr_getrectalloc ( ) retrieves it:
Revision A, of May 9,1988
192 SunView 1 System Programmer’s Guide
13.1. Minimal Repaint
Support
wmgr_setrectalloc(rootfd, tool_left, tool_top,
icon_left, icon_top)
int rootfd;
short tool_left, tool_top, icon_left, icon_top;
wmgr_getrectalloc(rootfd, tool_left, tool_top,
icon_left, icon_top)
int rootfd;
short *tool_left, *tool_top, *icon_left, *icon_top;
If you do a wmgr_setrectalloc (), make sure that all the values you are not
changing were retrieved with wmgr_getrect alloc (). In other words, both
procedures affect all the values.
This is an extremely advanced subsection used only for those who might want to
implement routines similar of the higher level window management routines
mentioned above. This section has strong connections to the Advanced Imaging
chapter and the chapter on Rects and Rectlists. Readers should refer to both from
here.
Moving windows about on the screen may involve repainting large portions of
their image in new places. Often, the existing image can be copied to the new
location, saving the cost of regenerating it. Two procedures are provided to sup¬
port this function:
win_computeclipping(windowfd)
int windowfd;
causes the window system to recompute the exposed and damaged rectlists for
the window identified by windowfd while withholding the SIGWINCH that
will tell each owner to repair damage.
win_partialrepair(windowfd, r)
int windowfd;
Rect *r;
tells the window system to remove the rectangle r from the damaged area for the
window identified by windowfd. This operation is a no-op if windowfd has
damage accumulated from a previous window database change, but has not told
the window system that it has repaired that damage.
Any window manager can use these facilities according to the following strategy:
□ The old exposed areas for the affected windows are retrieved and cached.
(pw_exposed())
□ The window database is locked and manipulated to accomplish the rear¬
rangement. (win_lockdata(), win_remove(), win setlink(),
win_setrect (), win insert (),...)
□ The new area is computed, retrieved, and intersected with the old.
(win_computeclipping(), pw exposed(),
rl_intersection())
mm
\r microsystems
Revision A, of May 9, 1988
Chapter 13 — Window Management 193
□ Pixels in the intersection are copied, and those areas are removed from the
subject window’s damaged area. (pw_lock (), pr_copy (),
win_partialrepair())
□ The window database is unlocked, and any windows still damaged get the
signals informing them of the reduced damage which must be repaired.
microsystems
Revision A, of May 9, 1988
.
14
Rects and Rectlists
Rects and Rectlists. 197
14.1. Rects. 197
Macros on Rects. 197
Procedures and External Data for Rects. 198
14.2. Rectlists. 199
Macros and Constants Defined on Rectlists. 200
Procedures and External Data for Rectlists . 200
14.1. Rects
Macros on Rects
Rects and Rectlists
This chapter describes the geometric structures and operations SunView provides
for doing rectangle algebra.
Images are dealt with in rectangular chunks. The basic structure which defines a
rectangle is the Rect. Where complex shapes are required, they are built up out
of groups of rectangles. The structure provided for this purpose is the
Rectlist.
These structures are defined in the header files <sunwindow/rect. h> and
<sunwindow/rect list. h>. The library that provides the implementation
of the functions of these data types is part of /usr/lib/libsunwindow. a.
The rect is the basic description of a rectangle, and there are macros and pro¬
cedures to perform common manipulations on a rect.
♦define coord short
typedef struct rect {
coord r_left;
coord r_top;
short r_width;
short r_height;
} Rect;
The rectangle lies in a coordinate system whose origin is in the upper left-hand
comer and whose dimensions are given in pixels.
The same header file defines some interesting macros on rectangles. To deter¬
mine an edge not given explicitly in the rect:
♦define rect_right(rp)
♦define rect_bottom(rp)
Rect *rp;
returns the coordinate of the last pixel within the rectangle on the right or bottom,
respectively.
Useful predicates returning TRUE or FALSE 32 are:
32 <sunwindow/rect .h> defines bool, TRUE and FALSE if they are not already defined.
microsystems
197
Revision A, of May 9, 1988
198 Sun View 1 System Programmer’s Guide
rect_isnull(r)
rect_includespoint(r,x,y)
rect__equal (rl, r2)
rect__includesrect (rl, r2)
rect intersectsrect(rl, r2)
/* r's width or height is 0
/* (x,y) lies in r
/* rl and r2 coincide
* exactly
/* every point in r2
* lies in rl */
/* at least one point lies
* in both rl and r2 */
*/
*/
*/
Rect *r, *rl, *r2;
coord x, y;
Macros which manipulate dimensions of rectangles are:
rect_construct(r, x, y, w, h)
Rect *r;
int x, y, w, h;
This fills in r with the indicated origin and dimensions.
rect_marginadjust(r, m)
Rect *r;
int m;
adds a margin of m pixels on each side of r; that is, r becomes 2*m larger in each
dimension.
rect_passtoparent(x, y,
rect_passtochild(x, y,
coord x, y;
Rect *r;
r)
r)
sets the origin of the indicated rect to transform it to the coordinate system of a
parent or child rectangle, so that its points are now located relative to the parent
or child’s origin, x and y are the origin of the parent or child rectangle within its
parent; these values are added to, or respectively subtracted from, the origin of
the rectangle pointed to by r, thus transforming the rectangle to the new coordi¬
nate system.
Procedures and External Data A null rectangle, that is one whose origin and dimensions are all 0, is defined for
for Rects convenience:
extern struct rect rect null;
The following procedures are also defined in rect. h:
Rect
rect_bounding(rl, r2)
Rect *rl, *r2;
This returns the minimal rect that encloses the union of r 1 and r2. The returned
value is a struct, not a pointer.
rect_intersection(rl, r2, rd)
Rect *rl, *r2, *rd;
computes the intersection of rl and r2, and stores that rect into rd.
microsystems
Revision A, of May 9, 1988
Chapter 14 — Rects and Rectlists 199
14.2. Rectlists
bool
rect_clipvector(r, xO, yO, xl, yl)
Rect *r;
int *x0, *y0, *xl, *yl;
modifies the vector endpoints so they lie entirely within the rect, and returns
FALSE if that excludes the whole vector, otherwise it returns TRUE.
NOTE This procedure should not be used to clip a vector to multiple abutting rectan¬
gles. It may not cross the boundaries smoothly.
bool rect_order(rl, r2, sortorder)
Rect *rl, *r2;
int sortorder;
returns TRUE if r 1 precedes or equals r 2 in the indicated ordering:
#define RECTS_TOPTOBOTTOM 0
#define RECTS_BOTTOMTOTOP 1
#define RECTS_LEFTTORIGHT 2
#define RECTS RIGHTTOLEFT 3
Two related defined constants are:
#define RECTS_UNSORTED 4
indicating a “don’t-care” order, and
#define RECTS_SORTS 4
giving the number of sort orders available, for use in allocating arrays and so on.
A Rect list is a structure that defines a list of rects. A number of rectangles
may be collected into a list that defines an interesting portion of a larger rectan¬
gle. An equivalent way of looking at it is that a large rectangle may be frag¬
mented into a number of smaller rectangles, which together comprise all the
larger rectangle’s interesting portions. A typical application of such a list is to
define the portions of one rectangle remaining visible when it is partially
obscured by others.
typedef struct rectlist {
coord rl_x, rl_y;
Rectnode *rl__head;
Rectnode *rl_tail,
Rect rl_bound;
} Rectlist;
typedef struct rectnode {
Rectnode *rn_next;
Rect rn_rect ;
} Rectnode;
Each node in the rectlist contains a rectangle which covers one part of the visible
whole, along with a pointer to the next node, r Inbound is the minimal bound¬
ing rectangle of the union of all the rectangles in the node list. All rectangles in
the rectlist are described in the same coordinate system, which may be translated
microsystems
Revision A, of May 9,1988
200 SunView 1 System Programmer’s Guide
efficiently by modifying rl_x and rl_y.
The routines that manipulate rectlists do their own memory management on
rectnodes, creating and freeing them as necessary to adjust the area described by
the rectlist.
Macros and Constants
Defined on Rectlists
Macros to perform common coordinate transformations are provided:
rl_rectoffset(rl, rs, rd)
Rectlist *rl;
Rect *rs, *rd;
copies rs into rd, and then adjusts rd’s origin by adding the offsets from rl.
rl_coordoffset(rl, x, y)
Rectlist *rl;
coord x, y;
offsets x and y by the offsets in r 1. For instance, it converts a point in one of
the rects in the rectnode list of a rectlist to the coordinate system of the rectlist’s
parent.
Parallel to the macros on rect’s, we have:
rl_passtoparent(x, y, rl)
rl_passtochild(x, y, rl)
coord x, y;
Rectlist *rl;
which add or subtract the given coordinates from the rectlist’s rl x and rl y
to convert the rl into its parent’s or child’s coordinate system.
Procedures and External Data
for Rectlists
An empty rectlist is defined, which should be used to initialize any rectlist before
it is operated on:
extern struct rectlist rl_null;
Procedures are provided for useful predicates and manipulations. The following
declarations apply uniformly in the descriptions below:
Rectlist *rl, *rll, *rl2, *rld;
Rect *r;
coord x, y;
Predicates return TRUE or FALSE. Refer to the following table for specifics.
microsystems
Revision A, of May 9, 1988
Chapter 14 — Rects and Rectlists 201
Table 14-1 Rectlist Predicates
Macro
Returns TRUE if
rl_empty(rl)
Contains only null rects
rl_equal(rll, rl2)
The two rectlists describe the same space identically —
same fragments in the same order
rl_includespoint(rl,x,y)
(x,y) lies within some rect of rl
rl_equalrect(r, rl)
rl has exactly one rect, which is the same as r
rl_boundintersectsrect(r, rl)
Some point lies both in r and in rl’s bounding rect
Manipulation procedures operate through side-effects, rather than returning a
value. Note that it is legitimate to use a rectlist as both a source and destination
in one of these procedures. The source node list will be freed and reallocated
appropriately for the result. Refer to the following table for specifics.
#$un
\r microsystems
Revision A, of May 9, 1988
202 Sun View 1 System Programmer’s Guide
Table 14-2 Rectlist Procedures
Procedure
Effect
rl_intersection(rll, rl2, rid)
Stores into rid a rectlist which covers the intersection of
rll and rl 2 .
rl_union(rll, rl2, rid)
Stores into rid a rectlist which covers the union of rll and
rl2.
rl difference(rll, rl2, rid)
Stores into rid a rectlist which covers the area of rll not
covered by rl 2 .
rl_coalesce(rl)
Attempts to shorten rl by coalescing some of its fragments.
Anri whose bounding rect is completely covered by the
union of its node rects will be collapsed to a single node;
other simple reductions will be found; but the general solu¬
tion to the problem is not attempted.
rl_sort(rl, rid, sort)
int sort;
rl is copied into rid, with the node rects arranged in sort
order.
rl_rectintersection (r, rl, rid)
rid is filled with a recdist that covers the intersection of r
and rl.
rl_rectunion(r, rl, rid)
rid is filled with a rectlist that covers the union of r and
rl.
rl_rectdifference(r, rl, rid)
rid is filled with a rectlist that covers the portion of rl
which is not in r.
rl_initwithrect(r, rl)
Fills in rl so that it covers the rect r.
rl_copy(rl, rid)
Fills in rid with a copy of rl.
rl free(rl)
Frees the storage allocated to rl.
rl_normalize(rl)
Resets rl’s offsets (rl_x, rl_y) to be 0 after adjusting the
origins of all rects in rl accordingly.
#su,n
\r microsystems
Revision A, of May 9, 1988
Scrollbars
Scrollbars. 205
15.1. Basic Scrollbar Management. 205
Registering as a Scrollbar Client. 205
Keeping the Scrollbar Informed. 206
Handling the SCROLL_REQUEST Event. 207
Performing the Scroll . 208
Normalizing the Scroll. 209
Painting Scrollbars. 209
15.2. Advanced Use of Scrollbars. 209
Types of Scrolling Motion in Simple Mode. 210
Types of Scrolling Motion in Advanced Mode. 211
Scrollbars
Canvases, text subwindows and panels have been designed to work with
scrollbars. The text subwindow automatically creates its own vertical scrollbar.
For canvases and panels, it is your responsibility to create the scrollbar and pass
it in via the attributes WIN_VERTICAL_SCROLLBAR or
WIN_HORIZONTAL_SCROLLBAR.
The chapter on scrollbars in the SunView Programmer’s Guide covers what most
applications need to know about scrollbars.
The material in this chapter will be of interest only if you are writing an applica¬
tion not based on canvases, text subwindows or panels, and you need to com¬
municate with the scrollbar directly as events are received. This chapter is
directed to programmers writing software which receives scroll-request events
and implements scrolling.
The definitions necessary to use scrollbars are found in the header file
<suntool/scrollbar.h>
15.1. Basic Scrollbar
Management
Registering as a Scrollbar The scrollbar receives events directly from the Notifier. The user makes a scroll
Client request by releasing a mouse button over the scrollbar. The scrollbar’s job is to
translate the button-up event into a scrolling request event, and send this event,
via the Notifier, to its client.
To receive scrolling request events, the client must register itself with the
scrollbar via the SCROLL_NOTIFY_CLIENT attribute. For example,
panel_l would register as a client of bar_l with the call:
r -s
scrollbar_set(bar_l, SCROLL_NOTIFY_CLIENT, panel_l, 0) ;
V_
NOTE Before registering with the scrollbar, the client must register with the Notifier by
calling win_register ().
In most applications, such as the panel example above, the client and the scrol¬
ling object are identical. However, they may well be distinct. In such a case, if
the client wants the scrollbar to keep track of which object the scrollbar is being
used with, the client has to inform the scrollbar explicitly of the object which is
205 Revision A, of May 9,1988
206 SunView 1 System Programmer’s Guide
to be scrolled. This is done by setting the SCROLL_OB JECT attribute.
For example, in the text subwindow package, the text subwindow is the client to
be notified. Within a given text subwindow there may be many views onto the
underlying file. Each of these views has its own scrollbar. So each scrollbar
created by the text subwindow will have the text subwindow as
SCROLL_NOTIFY_CLIENT and the particular view as SCROLL_OB JECT. So
to create scrollbars for two views, the text sub window package would call:
scrollbar_set(bar_l,
SCROLL_NOTIFY_CLIENT, textsubwindow_l,
SCROLL_OBJECT, view_l,
0 ) ;
scrollbar_set(bar_2,
SCROLL_NOTIFY_CLIENT, textsubwindow_l,
SCROLL_OBJECT, view_2,
0 ) ;
Keeping the Scrollbar The visible portion of the scrolling object is called the view into the object The
Informed scrollbar displays a bubble representing both the location of the view within the
object and the size of the view relative to the size of the object. In order to com¬
pute the size and location of the bubble, and to compute the new offset into the
object after a scroll, the scrollbar needs to know the current lengths of both the
object and the view.
The client must keep the scrollbar informed by setting the attributes
SCROLL_OBJECT_LENGTH and SCROLL_VIEW_LENGTH. There are two
obvious strategies for when to update this information. You can ensure that the
scrollbar is always up-to-date by informing it whenever the lengths in question
change. If this is too expensive (because the lengths change too frequently) you
can update the scrollbar only when the cursor enters the scrollbar.
This strategy of updating the scrollbar when it is entered can be implemented as
follows. When the scrollbar gets a LOC_RGNENTER or L0C_RGNEXIT event,
it causes the event-handling procedure of its notify client to be called with a
SCROLL_ENTER or SCROLL_EXIT event. The client then catches the
SCROLL_ENTER event and updates the scrollbar, as in the example below.
(Note that the scrollbar handle to use for the scrollbar_set () call is passed
in as arg).
microsystems
Revision A, of May 9, 1988
Chapter 15 — Scrollbars 207
Notify_value
panel_event_proc(client, event, arg, type)
caddr__t client;
Event *event;
Notify_arg arg;
Notify_event_type type;
{
switch (event_id(event)) {
case SCROLL_ENTER:
scrollbar_set((Scrollbar)arg,
SCROLL_OBJECT_LENGTH, current_ob j_length,
SCROLL_VIEW_START, current_view_start,
SCROLL_VIEW_LENGTH, current__view_length,
0 );
break;
}
}
The client can interpret the values of SCROLL_OB JECT_LENGTH,
SCROLL_VIEW_LENGTH and SCROLL_VIEW_START in whatever units it
wants to. For example, the panel package uses pixel units, while the text subwin¬
dow package uses character units.
Handling the When the user requests a scroll, the scrollbar client’s event-handling procedure
SCROLL_REQUEST Event gets called with an event whose event code is SCROLL_REQUEST. The event
proc is passed an argument (arg in the example below) for event-specific data.
In the case of scrollbar-related events, arg is a scrollbar handle (type
Scrollbar). As in the example below, the client’s event proc must switch on
the SCROLL_REQUEST event and call a procedure to actually perform the
scroll:
f -—-—s
Notify_value
panel_event_proc(panel, event, arg, type)
Panel panel;
Event *event;
Notify_arg arg;
Notify_event_type type;
{
switch (event_id(event)) {
case SCROLL_REQUEST:
do_scroll(panel, (Scrollbar)arg);
break;
}
}
V--- -
Revision A, of May 9,1988
208 Sun View 1 System Programmer’s Guide
Performing the Scroll
The new offset into the scrolling object is computed by the Scrollbar Package,
and is available to the client via the attribute SCROLL_VIEW_START. The
client’s job is to paint the object starting at the new offset, and to paint the
scrollbar reporting the scroll, so that its bubble will be updated to reflect the new
offset. So in the simplest case the client’s scrolling routine would look some¬
thing like this:
f —
d°_
scroll(sb)
{
Scrollbar sb;
unsigned new_view_start;
/* paint scrollbar to show bubble in new position */
scrollbar_paint(sb);
/* get new offset into object from scrollbar */
new view__start = (unsigned) scrollbar__get (sb.
SCROLL_VIEW_START) ;
}
/* client's proc to paint object at new offset */
paint object(sb->object, new_view_start);
J
If the client has both a horizontal and a vertical scrollbar, it will probably be
necessary to distinguish the direction of the scroll, as in:
-.
do_scroll(sb)
Scrollbar sb;
{
/* paint the scrollbar to show bubble in new position */
scrollbar_j?aint (sb) ;
/* get new offset into object from scrollbar */
/*
* pass the new offset and the direction of the scrollbar
* into the paint function
*/
paint__object (sb->object,
scrollbar_get(sb, SCROLL_VIEW_START),
scrollbar_get(sb, SCROLL_DIRECTION));
}
V-
In order to repaint the screen efficiently, you need to know which bits appear on
the screen both before and after the scroll, and thus can be copied to their new
location with pw_copy (). To compute the copyable region you will need, in
addition to the current offset into the object (SCROLL__VIEW_START ), the
offset prior to the scroll (SCROLL_LAST_VIEW_START).
Note: you are responsible for repainting the scrollbar after a scroll, with one of
the routines described later in Painting Scrollbars .
microsystems
Revision A, of May 9, 1988
Chapter 15 — Scrollbars 209
Normalizing the Scroll
Painting Scrollbars
15.2. Advanced Use of
Scrollbars
The scrollbar package can be utilized in two modes: normalized and un¬
normalized. Un-normalized means that when the user makes a scrolling request,
it is honored exactly to the pixel, as precisely as resolution permits. In normal¬
ized scrolling, the client makes an attempt to put the display in some kind of
"normal form" after the scrolling has taken place.
To take panels as an example, this simply means that after a vertical scroll, the
Panel Package modifies the value of SCROLL_VIEW_START so that the highest
item which is either fully or partially visible in the panel is placed with its top
edge SCR0LL_MARGIN pixels from the top of the panel.
Normalization is enabled by setting the SCROLL_NORMALIZE attribute for the
scrollbar to TRUE, and the SCROLL_MARGIN attribute to the desired margin.
SCROLL_NORMALIZE defaults to TRUE, and SCROLL_MARGIN defaults to
four pixels.
Note that the scrollbar package simply keeps track of whether the scrolls it com¬
putes are intended to be normalized or not. The client who receives the scroll-
request event is responsible for asking the scrollbar whether normalization
should be done, and if so, doing it.
After the client computes the normalized offset, it must update the scrollbar by
setting the attribute SCROLL_VIEW_START to the normalized offset.
The basic routine to paint a scrollbar is:
scrollbar_paint(scrollbar);
Scrollbar scrollbar;
scrollbar_paint () repaints only those portions of the scrollbar (page but¬
tons, bar proper, and bubble) which have been modified since they were last
painted. To clear and repaint all portions of the bar, use
scrollbar_paint_clear().
In addition, the routines scrollbar_paint_bubble () and
scrollbar_clear_bubble () are provided to paint or clear the bubble
only.
As indicated previously under Performing the Scroll, the client need not be con¬
cerned with the details of the scroll request at all — he may simply use the new
offset given by the value of the SCROLL_VIEW_START attribute. However, the
client may want to assume partial or full responsibility for the scroll. He may
compute the new offset from scratch himself, or start with the offset computed by
the Scrollbar Package and modify it so as not to have text or other information
clipped at the top of the window (see the preceding discussion under Normalizing
the Scroll).
In order to give you complete control over the scroll, attributes are provided to
allow you to retrieve all the information about the scroll-request event and the
object’s state at the time of the event The attributes of interest include:
V microsystems
Revision A, of May 9,1988
210 Sun View 1 System Programmer’s Guide
Table 15-1 Scroll-Related Scrollbar Attributes
Attribute
Value Type
Description
S CROL L_LAS T__VI E W_S TART
int
Offset of view into object prior to scroll.
Get only.
SCROLL_OBJECT
caddr_t
pointer to the scrollable object.
SCROLL_OBJECT_LENGTH
int
Length of scrollable object, in client
units (value must be >= 0). Default: 0.
SCROLL_REQUEST_MOTION
Scroll_motion
Scrolling motion requested by user.
SCROLL_REQUEST__OFFSET
int
Pixel offset of scrolling request into
scrollbar. Default: 0.
SCROLL_VIEW_LENGTH
int
Length of viewing window, in client units.
Default: 0.
SCROLL_VIEW_START
int
Current offset into scrollable object,
measured in client units.
(Value must be >= 0). Default: 0.
Types of Scrolling Motion in
Simple Mode
There are three basic types of scrolling motion:
□ SCROLL_ABSOLUTE. This is the “thumbing” motion requested by the user
with the middle button. You can retrieve the number of pixels into the
scrollbar of the request (including the page button which may be present) via
SCROLL_REQUEST_OFFSET.
□ SCROLL_FORWARD. This is to be interpreted as a request to bring the loca¬
tion of the cursor to the top (left, if horizontal).
□ S CROLL_BACKWARD . This is to be interpreted as a request to bring the top
(left, if horizontal) point to the cursor.
The function which implements scrolling may want to switch on the scrolling
motion, to implement different algorithms for each motion. In the following
example, do_absolute_scroll (), do_f orward_scroll (),
do_backward_scroll () and paint_ob ject () are procedures written
by the client:
Revision A, of May 9,1988
Chapter 15 — Scrollbars 211
do_scroll(sb)
Scrollbar sb;
{
unsigned new_offset;
Scroll_motion motion;
motion = (Scroll_motion) scrollbar_get(sb, SCROLL_MOTION);
switch (motion) {
case SCROLL__ABSOLUTE:
new__offset = do_absolute_scroll (sb) ;
break;
case SCROLL_FORWARD:
new_offset = do_forward_scroll(sb);
break;
case SCROLL_BACKWARD:
new_offset = do_backward_scroll(sb);
break;
}
/* tell the scrollbar of the new offset */
scrollbar_set(sb, SCROLL_VIEW_START, new_offset, 0);
/* paint scrollbar to show bubble in new position */
scrollbar_jpaint (sb) ;
/* client's repainting proc */
paint_object(scrollbar_get(sb, SCR0LL_0BJECT, 0);
Types of Scrolling Motion in Internally, the scrollbar package distinguishes nine different types of motion.
Advanced Mode depending on which mouse button the user pressed, the state of the shift key, and
the whether the cursor was in the bar, the forward page button or the backward
page button. Normally, these motions are mapped onto the three basic motions
described above. In order to perform this mapping, the scrollbar package needs
to know the distance between lines. You do this by setting the
SCROLL_LlNE_HEIGHT attribute, as in:
- ^
scrollbar_set(sb, SCROLL_LINE_HEIGHT f 20, 0) ;
>_
NOTE This is the distance, in pixels, from the top of one line to the top of the succeeding
line.
The scrollbar package can also be used in advanced mode, in which case the
mapping described above is not performed — the motion is passed as is to the
notify proc. This allows you to inteipret each motion exactly as you want.
The following table gives the nine motions, the user action which generates
them, and the basic motions which they are mapped onto (if not in advanced
#sun
\r microsystems
Revision A, of May 9, 1988
212 Sun View 1 System Programmer’s Guide
mode)
Table 15-2 Scrollbar Motions
Motion
Generated By
Mapped to
ABSOLUTE
POINT_TO_MIN
MAX_T 0_P 0 1 NT
PAGE_F ORWARD
LI NE__F ORWARD
MIN_TO_POINT
POINT_TO_MAX
PAGE_BACKWARD
LINE BACKWARD
middle in bar
left in bar
shifted left in bar
middle in page button
left in page button
right in bar
shifted right in bar
shifted middle in page button
right in page button
ABSOLUTE
FORWARD
FORWARD
FORWARD
FORWARD
BACKWARD
BACKWARD
BACKWARD
BACKWARD
To operate in advanced mode you must:
□ set the attribute SCROLL_ADVANCED_MODE to TRUE.
□ Switch on the nine motions in the above table. Note: specifically,
SCROLL_FORWARD and SCROLL_BACKWARD must not appear in your
switch statement. In other words, for basic mode switch on the three basic
motions; for advanced mode switch on the nine advanced motions.
Revision A, of May 9,1988
A
Writing a Virtual User Input Device
Driver
Writing a Virtual User Input Device Driver. 215
A.l. Firm Events. 215
The Firm_event Structure. 215
Pairs. 216
Choosing VUID Events. 217
A.2. Device Controls. 217
Output Mode. 217
Device Instancing. 217
Input Controls. 218
A.3. Example. 218
Writing a Virtual User Input Device
Driver
This section describes what a device driver needs to do in order to conform to the
Virtual User Input Device (vuid) interface understood by SunView. This is not a
tutorial on writing a device driver; only the vuid related aspects of device driver
writing are covered.
A.l. Firm Events
Firm event Structure
A stream of firm events is what your driver is expected to emit when called
through the read () system call. This stream is simply a byte stream that
encodes Firm_event structures. A firm event is a structure comprising an ID
which indicates what kind of event it is, the value of the event, and a time when
this event occurred; it also carries some information that allows the event’s even¬
tual consumer to maintain the complete state of its input system.
The Firm event structure is defined in <sundev/vuid event. h>:
typedef struct firm event {
u_short
u_char
u_char
int
struct timeval
} Firm event;
id;
pair_type;
pair;
value;
time;
#define FE_PAIR_NONE 0
#define FE_PAIR_SET 1
♦define FE_PAIR_DELTA 2
♦define FE PAIR ABSOLUTE 3
Here is what the fields in the Firm event mean:
a id — is the event’s unique identifier. It is either the id of an existing vuid
event (if you’re trying to emulate part of the vuid) or your one of your own
creation (see Choosing VUID Events).
a value — is the event’s value. It is often 0 (up) or 1 (down). For valuators
it is a 32 bit integer.
□
time — is the event’s time stamp, i.e., when it occurred. The time stamp is
not defined to be meaningful except to compare with other Firm_event
time stamps. In the kernel, a call to uniqt ime (), which takes a pointer to
a struct timeval, gets you a close-to-current unique time. In user
microsystems
215
Revision A, of May 9,1988
216 SunView 1 System Programmer’s Guide
process land, a call to gettimeof day(2) gets time from the same source
(but it is not made unique).
Pairs This brings us to pair_type and pair. These two fields enable a consumer
of events to maintain input state in an event-independent way. The pair field is
critical for a input state maintenance package, one that is designed to not know
anything about the semantics of particular events, to maintain correct data for
corresponding absolute, delta and paired state variables. Some examples will
make this clear:
□ Say you have a tablet emitting absolute locations. Depending on the client,
what the absolute location is may be important (say for digitizing) and then
again the difference between the current location and the previous location
may be of interest (say for computing acceleration while tracking a cursor).
□ Say you are keyboard in which the user has typed A C. Your driver first emits
a SHIFT_CTRL event as the control key goes down. Next your driver emits
a A C event (one of the events from the ASCII vuid segment) as the c key
goes down. Now the application that you are driving happens to be using
the c key as a shift key in some specialized application. The application
wants to be able to say to SunView (the maintainer of the input state), “Is
the c key down?” and get a correct response.
The vuid supports a notion of updating a companion event at the same time that a
single event is generated. In the first situations above, the tablet wants to be able
to update companion absolute and relative event values with a single event. In
the second situations above, the keyboard wants to be able to update companion
A C and c event values with a single event. The vuid supports this notion of
updating a companion event in such a way as to be independent from these two
particular cases. pair_type defines the type of the companion event:
□ FE_PAIR_NONE — is the common case in which pair is not defined, i.e.,
there is no companion.
□ FE_PAIR_SET — is used for ASCII controlled events in which pair is
the uncontrolled base event, e.g., A C and ’c’ or ’C’, depending on the state of
the shift key. The use of this pair type is not restricted to ASCII situations.
This pair type simply says to set the pairth event in id’s vuid segment to be
value.
□ FE_PAIR_DELTA — identifies pair as the delta companion to id. This
means that the pairth event in id’s vuid segment should be set to the
delta of id’s current value and value. One should always create vuid
valuator events as delta/absolute pairs. For example, the events
LOCXDELTA and LOC_X_ABSOLUTE are pairs and the events
LOC Y DELTA and LOC Y AB SOLUTE are pairs. These events are part
of the standard WORKSTATION DEVID segment that define the distin¬
guish primary locator motion events.
□ FE_PAIR_ABSOLUTE — identifies pair as the absolute companion to
id. This means that the pairth event in id’s vuid segment should be set
to the sum of id’s current value and value. One should always create vuid
Revision A, of May 9,1988
Appendix A — Writing a Virtual User Input Device Driver 217
valuator events as delta/absolute pairs.
As indicated by the previous discussion, pair must be in the same vuid segment
as id.
Choosing VUID Events
One needs to decide which events the driver is going to emit. If you want to
emulate the Sun virtual workstation then you want to emit the same events as the
WORKSTATION DEVID vuid segment. A tablet, for example, can emit abso¬
lute locator positions LOC X AB SOLUTE and LOC_Y_ABSOLUTE, instead
of a mouses relative locator motions LOCXDELTA and LOC Y DELTA.
SunView will uses these to drive the mouse.
If you have a completely new device then you want to create a new vuid seg¬
ment. This is talked about in the workstations chapter of the SunView System
Programmer’s Guide.
A.2. Device Controls
A vuid driver is expected to respond to a variety of device controls.
Output Mode
Many of you will be starting from an existing device driver that already speaks
its own native protocol. You may not want to flush this old protocol in favor of
the vuid protocol. In this case you may want to operate in both modes.
VUID*FORMAT ioct Is are used to control which byte stream format that an
input device should emit.
#define VUIDSFORMAT _IOW(v, 1, int)
♦define VUIDGFORMAT _IOR(v, 2, int)
♦define VUID_NATIVE 0
♦define VUID_FIRM_EVENT 1
VUIDSFORMAT sets the input device byte stream format to one of:
□ VUID_NATIVE — The device’s native byte stream format (it may be vuid).
□ VUID_FIRM_EVENT — The byte stream format is Firm_events.
An ermo of ENOTTY or EINVAL indicates that a device can’t speak
Firm events.
VUIDSFORMAT gets the input device byte stream format.
Device Instancing
VUID*ADDR ioctls are used to control which address a particular virtual user
input device segment has. This is used to have an instancing capability, e.g., a
second mouse. One would:
□ Take the current mouse driver, which emits events in the
WORKSTATION DEVID vuid segment.
□ Define a new vuid segment, say LOC2 DEVID.
□ Add LOC2_X_ABSOLUTE, LOC2_Y_ABSOLUTE, LOC2_X_DELTA
and LOC2_Y_DELTA to the LOC2_DEVID vuid segment at the same
offset from the beginning of the segment as LOC X ABSOLUTE,
LOC_Y_ABSOLUTE, LOC X DELTA and LOC Y DELTA in the
WORKSTATIONDEVID.
Xr microsystems
Revision A, of May 9, 1988
218 SunView 1 System Programmer’s Guide
□ Command a mouse to emit events using LOC2_DEVID’s segment address
and the mouse’s original low byte segment offsets. Thus, it would be emit¬
ting LOC2_X_DELTA and LOC2_Y_DELTA, which is what your applica¬
tion would eventually receive.
Here is the VUID*ADDR commands common data structure and command
definitions:
typedef struct vuid_addr_probe {
short base;
union {
short next;
short current;
} data;
} Vuid_addr_probe;
♦define VUIDSADDR _IOW(v, 3, struct vuid_addr_probe)
♦define VUIDGADDR _IOWR(v, 4, struct vuid addr_probe)
VUIDSADDR is used to set an alternative vuid segment, base is the vuid dev¬
ice addr that you are changing. A vuid device addr is the vuid segment id shifted
into it’s high byte position, data. next is the new vuid device addr that should
be used instead of base. An ermo of ENOTTY indicates that a device can’t deal
with these commands. An ermo of ENODEV indicates that the requested virtual
device has no events generated for it by this physical device.
VUIDGADDR is used to get an current value of a vuid segment, base is the
default vuid device addr that you are asking about, data. current is the
current vuid device addr that is being used instead of base.
The implementation of these ioctls is optional. If you don’t do it then your
device wouldn’t be able to support multiple instances.
Input Controls
Your device needs to support non-blocking reads in order to run with SunView
3.0. This means that the read(2) system call returns EWOULDBLOCK when no
input is available.
In addition, your driver should support the s elect (2) system call and asynchro¬
nous input notification (sending SIGIO when input pending). However, your
driver will still ran without these two things in 3.0 SunView.
A.3. Example
The following example is parts of code taken from the Sun 3.0 mouse driver. It
illustrates some of the points made above.
/* Copyright (c) 1985 by Sun Microsystems, Inc. */
<elided material>
#include "../sundev/vuid_event.h"
/*
* Mouse select management is done by utilizing the tty mechanism.
* We place a single character on the tty raw input queue whenever
w sun
Nr microsystems
Revision A, of May 9, 1988
Appendix A — Writing a Virtual User Input Device Driver 219
* there is some amount of mouse data available to be read. Once,
* all the data has been read, the tty raw input queue is flushed.
* Note: It is done in order to get around the fact that line
* disiplines don't have select operations because they are always
expected to be ttys that stuff characters when they get them onto
a queue.
Note: We use spl5 for the mouse because it is functionally the
same as spl6 and the tty mechanism is using spl5. The original
* code that was doing its own select processing was using spl6.
*/
#define spl_ms spl5
/* Software mouse registers */
struct ms__softc {
struct mousebuf {
short
short
struct
mb_size;
mb_of f ;
mouseinfo
/*
/*
size (in mouseinfo units) of buf */
current offset in buffer */
{
char
char
mi_x, mi_y;
mi_buttons;
0x4 /*
0x2 /*
0x1 /*
timeval mi_
/*
#define MS_HW_BUT1
#define MS_HW_BUT2
#define MS_HW_BUT3
struct
} mb__info[l];
} *ms_buf;
short ms__buf bytes; /*
short ms_flags; /*
short ms_oldoff; /*
short ms_oldoffl; /*
short ms__readformat; /*
#define MS_3BYTE_FORMAT VUID_NATIVE /*
#define MS VUID FORMAT VUID FIRM EVENT /*
short ms_vuidaddr;
short ms_vuidcount;
short ms_samplecount;
char ms readbuttons;
/*
/*
/*
/*
left button position */
middle button position */
right button position */
time; /* timestamp */
however many samples */
buffer size (in bytes) */
currently unused */
index into mousebuf */
at mi__x, mi_y or mi_buttons. . . */
format of read stream */
3 byte format (buts/x/y) */
vuid Firm_event format */
vuid addr for MS_VUID_FORMAT */
count of unread firm events */
count of unread mouseinfo samples
button state as of last read */
struct
msdata {
struct
struct
<elided material>
ms_softc msd_softc;
tty *msd_tp;
struct msdata msdata[NMS];
struct msdata *mstptomsd();
<elided material>
m sun
microsystems
Revision A, of May 9, 1988
220 Sun View 1 System Programmer’s Guide
/* Open a mouse. Calls sets mouse line characteristics */
/* ARGSUSED */
msopen(dev, tp)
dev_t dev;
struct tty *tp;
{
register int err, i;
struct sgttyb sg;
register struct mousebuf *b;
register struct ms_softc *ms;
register struct msdata *msd;
caddr_t zmemall();
register struct cdevsw *dp;
found:
/* See if tp is being used to drive ms already. */
for (i = 0;i < NMS; ++i)
if (msdata[i].msd_tp == tp)
return(0);
/* Get next free msdata */
for (i = 0;i < NMS; ++i)
if (msdata [i] .msd__tp == 0)
goto found;
return(EBUSY) ;
/*
if
/*
(caddr__t) &sg, 0) )
(caddr_t)&sg, 0))
Open tty */
(err = ttyopen(dev, tp) )
return(err);
Setup tty flags */
dp = &cdevsw[major(dev)];
if (err = (*dp->d_ioctl) (dev, TIOCGETP,
goto error;
sg.sg__flags = RAW+ANYP;
sg.sg_ispeed = sg.sg_ospeed = B1200;
if (err = (*dp->d_ioctl) (dev, TIOCSETP,
goto error;
/* Set up private data */
msd = &msdata[i];
msd->msd_xnext = 1;
msd->msd__tp = tp;
ms = &msd->msd_softc;
/* Allocate buffer and initialize data */
if (ms->ms_buf == 0) {
ms->ms_buf bytes = MS_BUF_BYTES ;
b = (struct mousebuf *)zmemall(memall, ms->ms_bufbytes);
if (b — 0) {
err = EINVAL;
goto error;
)
b->mb_size = 1 + (ms->ms_bufbytes-sizeof (struct mousebuf))
/ sizeof (struct mouseinfo);
ms->ms_buf = b;
ms->ms_vuidaddr = VKEY_FIRST;
msflush(msd);
W sun
V microsystems
Revision A, of May 9,1988
Appendix A — Writing a Virtual User Input Device Driver 221
}
return (0) ;
error:
bzero((caddr_t)msd, sizeof (*msd));
bzero((caddr_t)ms, sizeof (*ms));
return (err);
}
/*
* Close the mouse
*/
msclose(tp)
struct tty *tp;
{
register struct msdata *msd = mstptomsd(tp);
register struct ms_softc *ms;
if (msd == 0)
return;
ms = &msd->msd_softc;
/* Free mouse buffer */
if (ms->ms_buf != NULL)
wmemfree ( (caddr__t)ms->ms_buf, ms->ms_bufbytes) ;
/* Close tty */
ttyclose(tp);
/* Zero structures */
bzero((caddr_t)msd, sizeof (*msd));
bzero ( (caddr__t) ms, sizeof (*ms) ) ;
}
/*
* Read from the mouse buffer
*/
msread(tp, uio)
struct tty *tp;
struct uio *uio;
{
register struct msdata *msd = mstptomsd(tp);
register struct ms_softc *ms;
register struct mousebuf *b;
register struct mouseinfo *mi;
register int error = 0, pri f send___event, hwbit;
register char c;
Firm_event fe;
if (msd == 0)
return(EINVAL);
ms = &msd->msd_softc;
b = ms->ms_buf;
pri = spl_ms();
/*
* Wait on tty raw queue if this queue is empty since the tty is
* controlling the select/wakeup/sleep stuff.
m sun
Nr microsystems
Revision A, of May 9, 1988
222 Sun View 1 System Programmer’s Guide
*/
while
}
while
(tp->t__rawq.c_cc <= 0) {
if (tp->t__state&TS_NBIO) {
(void) splx(pri);
return (EWOULDBLOCK);
}
sleep((caddr_t)&tp->t_rawq, TTIPRI);
(lerror && (ms->ms_oldoff1 || ms->ms_oldoff
mi = &b->mb_inf o [ms->rns__oldof f ] ;
switch (ms->ms_readformat) {
!= b->mb off)) {
<elided material>
case MS_3BYTE_FORMAT:
break;
case MS_VUID_FORMAT:
if (uio->uio_resid < sizeof (Firm_event))
goto done;
send_event = 0;
switch (ms->ms_oldoff1++) {
case 0: /* Send x if changed */
if (mi->mi_x != 0) {
fe.id = vuid__id__addr (ms->ms_vuidaddr) |
vuid_id__of f set (LOC_X_DELTA) ;
fe.pair_type = FE_PAIR_ABSOLUTE;
fe .pair = LOC__X__ABSOLUTE;
fe.value = mi->mi_x;
send event = 1;
break;
case Is /* Send y if changed */
if (mi->mi__y != 0) {
fe.id = vuid_id_addr(ms->ms_vuidaddr) |
vuid_id_offset(LOC_Y_DELTA);
fe.pair_type = FE_PAIR_ABSOLUTE;
fe.pair = LOC_Y_ABSOLUTE;
fe.value = -mi->mi_y;
send_event = 1;
}
break;
default:/* Send buttons if changed */
hwbit = MS_HW_BUT1 » (ms->ms_oldoff 1 - 3) ;
if ((ms->ms_readbuttons & hwbit) !=
(mi->mi_buttons & hwbit)) {
fe.id = vuid__id_addr (ms->ms_vuidaddr) |
vuid_id_offset(
BUT(1) + (ms->ms_oldoff1 - 3) ) ;
fe.pair_type = F E_P AIR_NONE;
fe.pair = 0;
As
sun
microsystems
Revision A, of May 9, 1988
Appendix A — Writing a Virtual User Input Device Driver 223
/* Update read buttons and set value */
if (mi->mi_buttons & hwbit) {
fe.value = 0;
ms->ms__readbuttons | = hwbit;
} else {
fe.value = 1;
ms->ms_readbuttons &= ~hwbit;
}
send__event = 1;
}
/* Increment mouse buffer pointer */
if (ms->ms_oldoff1 == 5) {
ms->ms_oldof f++;
if (ms->ms__oldoff >= b->mb_size)
ms->ms_oldoff = 0;
ms->ms_oldoff1 = 0;
}
break;
}
if (send_event) {
fe.time = mi->mi_time;
ms->ms_vuidcount—;
/* lower pri to avoid mouse droppings */
(void) splx(pri);
error = uiomove(&fe f sizeof(fe) f UIO_READ f uio);
/* spl_ms should return same priority as pri */
pri = spl_ms();
}
break;
/* Flush tty if no more to read */
if ((ms->ms_oldoff1 == 0) && (ms->ms_oldoff == b->mb_off))
ttyflush(tp, FREAD);
/* Release protection AFTER ttyflush or will get out of sync with tty */
(void) splx(pri);
return (0);
/* Mouse ioctl */
msioctl(tp, cmd, data, flag)
struct tty *tp;
int cmd;
caddr_t data;
int flag;
{
register struct msdata *msd = mstptomsd(tp);
register struct ms_softc *ms;
int err = 0, num;
register int buf_off, read_off;
W sun
\T microsystems
Revision A, of May 9,1988
224 Sun View 1 System Programmer’s Guide
Vuid_addr_probe *addr_j?robe ;
if (msd == 0)
return(EINVAL);
ms = &msd->msd_softc;
switch (cmd) {
case FIONREAD:
switch (ms->ms_readformat) {
case MS_3BYTE__FORMAT:
Mint *)data = ms->ms_samplecount;
break;
case MS_VUID_FORMAT:
Mint *)data = sizeof (Firm_event) * ms->ms_vuidcount;
break;
}
break;
case VUIDSFORMAT:
if (Mint *)data == ms->ms_readformat)
break;
ms->ms_readformat = Mint *)data;
/*
* Flush mouse buffer because otherwise ms_*counts
* get out of sync and some of the offsets can too.
*/
msflush(msd);
break;
case VUIDGFORMAT:
Mint *)data = ms->ms__readformat;
break;
case VUIDSADDR:
addr_^probe = (Vuid_addr_probe *)data;
if (addr_j>robe->base != VKEY__FIRST) {
err = ENODEV;
break;
}
ms->ms_vuidaddr = addr_jDrobe->data.next;
break;
case VUIDGADDR:
addr_probe = (Vuid_addr_jprobe *)data;
if (addr__probe->base != VKEY_FIRST) {
err = ENODEV;
break;
}
addr__probe->data . current = ms->ms_vuidaddr;
break;
case TIOCSETD:
/*
m sun
\r microsystems
Revision A, of May 9, 1988
Appendix A — Writing a Virtual User Input Device Driver 225
* Don't let the line discipline change once it has been set
* to a mouse. Changing the ldisc causes msclose to be called
* even if the ldisc of the tp is the same.
* We can't let this happen because the window system may have
* a handle on the mouse buffer.
* The basic problem is one of having anything depending on
* the continued existence of ldisc related data.
* The fix is to have:
* 1) a way of handing data to the dependent entity, and
* 2) notifying the dependent entity that the ldisc
* has been closed.
*/
break;
(<elided material>
default:
err = ttioctl(tp, cmd, data, flag);
}
return (err);
msflush(msd)
register struct msdata *msd;
{
register struct ms_softc *ms = &msd->msd_softc;
int s = spl_ms();
<elided material>
ttyflush(msd->msd_tp, FREAD);
(void) splx(s);
}
<elided material>
/* Called with next byte of mouse data */
/*ARGSUSED*/
msinput (c, tp)
register char c;
struct tty *tp;
{
int s = spl5();
<elided material>
/* Place data on circular buffer */
if (wake)
/* Place character on tty raw input queue to trigger select */
ttyinput (' \ 0', msd->msd__tp) ;
(void) splx(s);
}
sun
microsystems
Revision A, of May 9,1988
226 Sun View 1 System Programmer’s Guide
/* Match tp to msdata */
struct msdata *
mstptomsd(tp)
struct tty *tp;
{
register i;
/* Get next free msdata */
for (i = 0;i < NMS; ++i)
if (msdata[i].msd_tp == tp)
return(&msdata[i]);
printf("mstptomsd called with unknown tp %X\n", tp) ;
return(0);
Revision A, of May 9,1988
B
Programming Notes
Programming Notes. 229
B.l. What Is Supported?. 229
B.2. Library Loading Order. 229
B.3. Shared Libraries vs. Shared Text. 229
Shared Libraries. 229
B.4. Error Message Decoding. 230
B.5. Debugging Hints. 230
Disabling Locking . 230
B.6. Sufficient User Memory. 231
B.7. Coexisting with UNIX. 232
Tool Initialization and Process Groups. 232
Signals from the Control Terminal. 232
Job Control and the C Shell. 232
B.l. What Is Supported?
B.2. Library Loading
Order
B.3. Shared Libraries vs.
Shared Text
Shared Libraries
Programming Notes
Here are useful hints for programmers who use SunView.
In each release, there may be some difference between the documentation and the
actual product implementation. The documentation describes the supported
implementation. In general, the documentation indicates where features are only
partially implemented, and in which directions future extensions may be
expected. Any necessary modifications to SunView are accompanied by a
description of the nature of the changes and appropriate responses to them.
When loading programs, remember to load higher level libraries first, that is, -
lsuntool -lsunwindow -lpixrect.
Starting with release 3.2 of SunOS, the tools in SunView were distributed as two
huge toolmerge files in order to reduce the working set requirements of SunView.
Instead of having many different programs running, each including its own copy
of the libsuntool. a, libsunwindow. a and libpixrect. a libraries,
several copies of one large program would run at once.
With the advent of shared libraries in SunOS release 4.0, toolmerging is unneces¬
sary in most cases. By default, each tool is compiled and linked to use shared
libraries, so the code of the SunView 1 libraries is still shared. 33 This also has the
benefit of greatly reducing the size of SunView 1 binaries. Another benefit is
that programs will automatically benefit from improvements in the SunView 1
libraries in each release, without recompilation.
You may find old programs or Makefiles with references to -DMERGE or -
DSTANDALONE in them.
Should you want to compile a program with static libraries, just supply the -
Bstat ic flag to the link editor or C compiler (read the ld(l) man page for
details). One reason to use static libraries is that it simplifies part of the debug¬
ging process.
33 The standard C library and many others are shared also.
XT microsystems
229
Revision A, of May 9,1988
230 SunView 1 System Programmer’s Guide
B.4. Error Message
Decoding
B.5. Debugging Hints
Disabling Locking
The default error reporting scheme described in Section 5.12, Error Handling,
displays a long hexadecimal number which is the ioct 1 number associated with
the error. You can turn this number into a more meaningful operation name by:
□ turning the two least significant digits into a decimal number;
□ searching /usr/include/sunwindow/win_ioctl .h for
occurrences of this number; and
□ noting the ioct 1 operation associated with this number.
This can provides a quick hint as to what is being complained about without
resorting to a debugger.
When debugging non-terminal oriented programs in the window system, there
are some things that you should know to make things easier.
As discussed mentioned in passing a process receives a SIGWINCH whenever
one of its windows changes state. In particular, as soon as a frame is shown, the
kernel sends it a SIGWINCH. When running as the child of a debugger, the
SIGWINCH is sent to the parent debugger instead of to the tool. By default, dbx
simply propagates the SIGWINCH to the tool, while adb traps, leaving the tool
suspended until the user continues from adb. This behavior is not peculiar to
SIGWINCH: adb traps all signals by default, while dbx has an initial list of sig¬
nals (including SIGWINCH) that are passed on to the child process. You can
instruct adb to pass SIGWINCH on to the child process by typing lc : i
I Return 1 . lc is the hex number for 28, which is SIGWlNCH’s number. Re¬
enable signal breaking by typing lc : 1 1 Return I . You can instruct dbx to trap
on a signal by using the catch command.
For further details, see the entries for the individual debuggers in the User’s
Manual for the Sun Workstation. In addition, ptrace(2) describes the fine
points of how kernel signal delivery is modified while a program is being
debugged.
The two debuggers differ also in their abilities to interrupt programs built using
tool windows, dbx knows how to interrupt these programs, but adb doesn’t.
See Signals from the Control Terminal below for an explanation.
Another situation specific to the window system is that various forms of locking
are done that can get in the way of smooth debugging while working at low lev¬
els of the system. There are variables in the sunwindow library that disable the
actual locking. These variables can be turned on from a debugger:
microsystems
Revision A, of May 9,1988
Appendix B — Programming Notes 231
Table B-l
Variables for Disabling Locking
Variable!Action
int
pixwindebug
When not zero this causes the immediate release of the display
lock after locking so that the debugger is not continually getting
hung by being blocked on writes to screen. Display garbage can
result because of this action.
int
win_lockdatadebug
When not zero, the data lock is never actually locked, preventing
the debugger from being continually hung during block writes to
the screen. Unpredictable things may result because of this
action that can’t properly be described in this context.
int
win_grabiodebug
When not zero will not actually acquire exclusive I/O access
rights so that the debugger wouldn’t get hung by being blocked
on writes to the screen and not be able to receive input. The
debugged process will only be able to do normal display locking
and be able to get input only in the normal way.
int
fullscreendebug
Like win_grabiodebug but applies to the fullscreen access
package.
Change these variables only during debugging. You can set them any time after
main has been called.
B.6. Sufficient User To use the SunView environment comfortably requires adequate user memory
Memory for SunView and SunOS, Sun’s operating system. To achieve the best perfor¬
mance, you must reconfigure your own kernel, deleting unused device drivers
and possibly reducing some tuning parameters. The procedure is documented in
the manual Installing the SunOS. You will be able to reclaim a significant
amount of usable main memory.
microsystems
Revision A, of May 9,1988
232 SunView 1 System Programmer’s Guide
B.7. Coexisting with UNIX This section discusses how a SunView tool interacts with traditional UNIX
features in the areas of process groups, signal handling, job control and terminal
emulation. If you are not familiar with these concepts, read the appropriate por¬
tions (Process Groups, Signals) of the System Services Overview, and the sig-
nal(3) and tty(4) entries in the SunOS Reference Manual.
This discussion explicitly notes those places where the shells and debuggers
interact differently with a tool.
System calls made by the library code in a tool affect the signals that will be sent
to the tool. A tool acts like any program when first started: it inherits the process
group and control terminal group from its parent process. However, when a
frame is created, the tool changes its process group to its own process number.
The following sections describe the effects of this change.
When the C shell (see csh(l)) starts a program, it changes the process group of
the child to the child’s process number. In addition, if that program is started in
the foreground, the C shell also modifies the process group of the control termi¬
nal to match the child’s new process group. .Thus, if the tool was started from the
C shell, the process group modification done by window_create () has no
effect.
The Bourne Shell (see sh(l)) and the standard debuggers do not modify their
child’s process and control terminal groups. Furthermore, both the Bourne Shell
and adb(l) are ill-prepared for the child to perform such modification. They do
not propagate signals such as SIGINT to the child because they assume that the
child is in the same control terminal group as they are. The bottom-line is that
when a tool is executed by such a parent, typing interrupt characters at the parent
process does not affect the child, and vice versa. For example, if the user types
an interrupt character at adb while it is debugging a tool, the tool is not inter¬
rupted. Although dbx(l) does not modify its child’s process group, it is
prepared for the child to do so.
Job Control and the C Shell The terminal driver and C shell job control interact differently with tools. First,
let us examine what happens to programs using the graphics subwindow library
package 34 When the user types an interrupt character on the control terminal, a
signal is sent to the executing program. When the signal is a SIGTSTP, the
gf xsw library code sees this signal and releases any SunView locks that it might
have and removes the graphics from the screen before it actually suspends the
program. If the program is later continued, the graphics are restored to the
screen.
However, when the user types the C shell’s stop command to interrupt the exe¬
cuting program, the C shell sends a SIGSTOP to the program and the gf xsw
library code has no chance to clean up. This causes problems when the code has
acquired any of the SunView locks, as there is no opportunity to release them.
Depending on the lock timeouts, the kernel will eventually break the locks, but
Signals from the Control
Terminal
Tool Initialization and Process
Groups
34 The gfxsubwindow is an out-dated package used only as an example.
Nr microsystems
Revision A, of May 9,1988
Appendix B — Programming Notes 233
until then, the entire screen is unavailable to other programs and the user. To
avoid this problem, the user should send the C shell kill command with the
—TSTP option instead of using stop.
The situation for tools parallels that of the gf xsw code. Thus a tool that wants
to interact nicely with job control must receive the signals related to job control
>L SIGINT , ( SIGQUIT, and SIGTSTP) and release any locks it has acquired.
If the tool is later continued, the tool must receive a SIGCONT so that it can
reacquire the locks before resuming the window operations it was executing.
The tool will still be susceptible to the same problems as the gf xsw code when
it is sent a SIGSTOP.
A final note: the user often relies on job control without realizing it; the expecta¬
tion is that typing interrupt characters will halt a program. Of course, even pro¬
grams that do not use SunView facilities, such as a program that opens the termi¬
nal in “raw” mode, have to provide a way to terminate the program. A program
using the gf xsw package that reads any input can provide limited job control by
calling gfxsw_inputinterrupt s.
Revision A, of May 9,1988
Index
A
adb(l), 232
the Agent, 21, 13
notification of tiles, 23
posting notification to tiles, 24
removing a tile from, 26
SunView 1 model, 14
architecture, 7
ASCI I_DEVI D, 54
B
bell, 37
blanket window, 41
bool, 197
Bourne Shell, 232
c
C shell, 232
job control, 232
caret, 59, 96
client handle, used by win_register (), 21
clipping, 14
close(2), 91
color
screen foreground and background colors, 48
colormap
segment, 16
segments, 15
shared, 16
coord type for Rects, 197
Copy function-key processing, 104
csh(l), 232
cursor, 15
Cut function-key processing, 104
D
dbx, 230, 232
debugging, 230
disabling locking, 230
fullscreendebug, 230
pixwindebug, 230
win__grabiodebug, 230
win_lockdatadebug, 230
defaults, 145
creating . d files, 149
default value, 146
defaults, continued
directory, 146
distinguished names, 148
enumerated option, 148
error handling, 156
Error_Action, 150, 156
example, 149
example program, 160
master and private defaults databases, 146
MaximumJErrorS, 157
option names, 147
option values, 148
private options, 146
Private-Directory, 146
Private only, 147
Test_Mode, 157
Testmode, 146
defaults database, 145
defaults functions
defaults_exists (),157
defaults_get (), 150
defaults_get_boolean (), 151, 157
def aults_get_character (), 151, 157
defaults_get_chiId (), 157
defaults_get_default (), 158
defaults_get_enum(), 152, 158
defaults_get_integer (), 150, 158
def ault s_get_integer_check (), 151, 158
defaults_get_sibling (), 158
defaults_get_string (), 150,158
def aults_reread (), 158
def ault s_set_chara cter (), 158
def ault s_set_enume rat ion (), 159
def ault s_set_integer (), 159
def aults_set_string, 159
def ault s__special_mode () , 159
def ault s_write_all (), 159
defaults_write_changed(>,159
def ault s_write_dif£erences(), 159
<sunwindow/defaults.h>, 145
DEFAULTS_UNDEFINED, 149
desktop, 47, 11,15 ,—also see screen
accessing the root fd, 50
foreground and background colors, 48
frame buffer, 48
keyboard, 48
locking, 16
mouse, 48
- 235 -
Index — Continued
desktop, continued
root window, 48
screen, 48
DESTROY_CHECKING, 80, 85
DESTROY_PROCESS_DEATH, 80
display
locking, 16
documentation
outline of this document, 7
pixrect vs. application vs. system manuals, 3
dup(2), 91
E
enumerated values
retrieving, 152
environment
SunView application usage, 42
window usage, 41
error
WIN ioctl errors, 43,230
Error_action, 150
event
client, 68, 81
client even t__f unc (), 69
delivery, 68, 77
dispatching, 67, 68, 82, 86
handlers, 67
interposition, 69
ordering, 67, 81
posting, 68, 69, 77
posting client events, 77
posting destroy, 80
retrieving event handler, 70
event codes
SCROLL_ENTER, 206
SCROLL_EXIT, 206
SCROLL_REQUEST, 207
event_func (), 24, 69
EWOULDBLOCK, 39
example programs
defaults, 160
filerjdefaulty 160
get_selection , 125
seln_demo , 128
exception_func (), 70
F
FALSE, 197
FASYNC, 39
FBIONREAD, 40
fcntia 39
fd_set, 82
FE_PAIR_ABSOLUTE, 215
FE_P AI R__DELTA, 215
FE_P AI R_NONE, 215
FE_PAIR_SET, 215
file descriptor
window, 13, 30
Find function-key processing, 104
FIOASYNC, 39, 91
FIONBIO, 39,91
Firm_event, 59,215
flash, 37
FNDELAY, 39
focus, 58
frame buffer, 48
fullscreen, 181
coordinate space, 181
grab I/O, 182
initializing, 182
pixel caching, 183
pixwin operations, 184
saving and restoring image, 183
struct fullscreen, 181
surface preparation, 182
use menu and alert packages instead, 181
use window__loop () instead, 181
window boundary violation, 183
fullscreen functions
fullscreen_destroy (), 182
f ullscreen_init (), 182
fullscreen_pw__copy (), 185
fullscreen_pw_vector (), 184
fullscreen_pw_write (), 184
pw_prepa re surface (), 183
pw_restore_pixels (), 184
pw_save_pixels (), 183
fullscreendebug, 230
function key processing, 104
G
geometry of rectangles, see rect
get_selection example program, 125
gfxsw, 233
H
header files
<sundev/vuid_event .h>, 55, 215
<suntool/scrollbar.h>, 205
<suntool/selection__attributes ,h>, 110
<suntool/selection_svc.h>, 110
<sunwindow/attr,h>, 110
<sunwindow/defaults.h>, 145
<sunwindow/rect.h>, 197
<sunwindow/rectlist.h>, 197
<sunwindow/win_enum.h>, 35
<sunwindow/win__input. h>), 55
<sunwindow/window_hs.h>, 29
i
icon, 174
dynamic loading, 174
file format, 174
template, 174
icon_init_f rom_pr (), 174
icon_load (), 174
icon_load_mpr (), 174
icon_open_header(), 175
IM_ASCII, 38
IM_INTRANSIT, 38
IM_META, 38
IM_NEGASCII, 38
- 236 -
Index — Continued
IM_NEGEVENT, 38
IM_NEGMETA, 38
imaging
fixup, 173
input, 37, see (mostly) workstation and vuid
SIGIO, 39
ascii, 38
asynchronous, 39
blocking, 39
bytes pending, 40
caret, 59
changing interrupt user actions, 63
current event, 60
current event lock, 60
current event lock broken, 60
designee, 39
events pending, 40
flow of control, 39
keyboard mask, 39
masks, 37
meta, 38
negative events, 38
non-blocking, 39
pick mask, 39
reading, 39
redirection, 39
releasing the current event lock, 60
seizing all, 182
state, 55
synchronization, 60, 61
synchronous, 39
unencode, 55
input device
control, 56
enumeration, 58
query, 57
removal, 57
setting and initialization, 57
input focus, 58, 59
getting the caret event, 59
keyboard, 58
restoring the caret, 59
setting the caret event, 59
input_imnull (), 38
input_readevent, 39
inputmask, 37
ioctl(2), 91
ITIMERJREAL, 81
ITIMER_VIRTUAL, 81
J
job control, 232
K
KBD_REQUEST, 58
kernel tuning, 61
win_disable_shared_locking, 62
winclistcharsmax, 62
ws_check_lock, 62
ws_check_time, 62
ws_f ast_poll_duration, 62
ws_fast_timeout, 61
kernel tuning, continued
ws_loc_still, 62
ws_lock__limit, 62
ws_set_f avor, 62
ws_slow_timeout, 62
ws_vq_node_bytes, 61
keyboard, 56
focus, 58
unencoded input, 55
KIOCTRANS, 55
L
LOC_RGNENTER, 24
LOC_RGNEXIT, 24
M
menu, see fullscreen
mouse, 56
sample vuid driver, 218
N
Notifier, 67, 13
advanced usage, 67
client, see client
client event handlers, 68
client events, 68
copy_func () calling sequence, 79
destroy event delivery time, 80
error codes, 88
event delivery time, 77
exception event handlers, 70
interaction with various system calls, 91
interposition, 72
miscellaneous issues, 91
notification, 68
output event handlers, 69
output events, 69
posting destroy events, 80
posting events, 77
posting events with an argument, 78
prioritization, 81
registering an interposer, 72
release_func () calling sequence, 79
restrictions, 67, 90,
safe destruction, 80
storage management during event posting, 78
Notifier functions
notify_client (), 86
notify_die(), 85
not if y__event (), 82
notify_exception (),83
notify_get__client_func (), 70
notify_get_destroy_func (), 71
notify_get_event_func (), 70
notify_get_exception__func (), 70, 71
notify_get_input_func (), 70
not ify_get_itimer__func (), 71
notify_get_output_func (), 70
notify_get_prioritizer_func (), 83
notify_get_scheduler_func (), 87
notify_get_signal_func (), 71
notify__get__wait3_func (), 71
notify_input (), 82
-237-
Index — Continued
Notifier functions, continued
notify_interpose_destroy__func (), 73
notify_interpose_event_func (), 72
notify_interpose_exception__func (), 73
notify__interpose_input_func (), 72
notify_interpose_itimer_func (), 73
notify__interpose_output_func (), 73
notify_interpose_signal_func (), 73
notify_interpose_wait3_func (), 73
notify_itimer (), 83
notify_next_destroy_func (), 74
notify_next_event__func (), 72, 74
notify_next_exception_func (), 74
notify_next_input_func (), 74
notify_next_it imer_func (), 74
notify_next_output_func(), 74
notify_next_signal_func(), 74
notify__next_wait3_func (), 74
notify_output (), 82
notify_perror (), 89
notify_post_destroy (), 80, 85
notify_post_event (), 69, 77
notify_post_event_and_arg (), 78, 79
notify_remove (), 87
notify_remove_destroy_func (), 75
notify_remove_event_func (), 75
notify_remove_exception_func (), 75
notify__remove_input_func (), 75
notify_remove_itimer_func (), 75
notify_remove_output_func (), 75
notify_remove_signal_func (), 75
notify_remove_wait3_func (), 75
notify_set_event__func (), 68, 72
notify_set__exception_func (), 70
notify_set_output__func (), 69
notify_set_j?rioritizer_func (), 81
notify_set__scheduler_func (), 86
notify_signal (), 83
notify_start (), 85
not if y_stop (), 85
notify_veto_destroy (), 85
not if y_wait3 (), 83
Notify_arg, 69, 79
NOT IF Y_BAD_F D, 70
NOT IF Y_BAD_I TIMER, 88
NOT IF Y_BAD_S IGNAL, 88
NOTIFY_BADF, 88
NOT I FY_CL IENT_NULL, 86
Notify_copy, 79
NOTIFY_COPY_NULL, 79
NOTIFY_DESTROY_VETOED, 80, 85, 88
NOTIFY_DONE, 69, 82
notify_errno, 73, 88
Notify_error, 88
Notify_event, 77
Notify_event_type, 68
NOTIFYJFUNC_LIMIT, 73, 89
NOT IF Y_F UNC__NULL, 70, 84
NOTIFY_I GNORED, 69, 77, 82
NOT IF Y__I MMEDI ATE, 68, 77
NOTIFY_INTERNAL_ERROR, 88
NOTIFY_INVAL, 80, 89
NOTIFY_N0_C0NDITI ON, 70, 73, 77, 83, 88
NOTIFY_NOMEM, 88
NOTIFY_NOT_STARTED, 85, 88
NOTIFYJDK, 73, 88
Notify_release, 79
NOT IFY_RELEASE__NULL, 79
NOT IF Y_SAFE, 68, 77
NOTIFY_SRCH, 88
NOT IFY_UNKNOWN_CLI ENT, 70, 73, 77, 83, 88
o
output_f unc (), 69
P
PANEL_DEVID, 54
Paste function-key processing, 104
pixwin, 13
closing, 37
colormap, 16
colormap segment, 15
creation, 36
damage, 176
damage report, 177
destruction, 37
flashing, 37
locking, 16
offset control, 178
opening, 36
region, 21
repair of retained pixwin, 177
repairing damage, 176
retained, 177
signals, 176
SIGWINCH, 176
surface preparation, 183
pixwin functions and macros
pw_close (), 37
pw_damaged (), 176
pw_donedamaged (), 177
pw_exposed(), 173
pw_get_x_off set (), 178
pw_get_y_of f set (), 178
pw_open (), 21, 36
pw_prepa re surface (), 183
pw_region (), 21
pw__repairretained (), 177
pw_restore_pixels (), 184
pw__restrict_clipping (), 173
pw_save_jpixels (), 183
pw_set_region_rect (), 24
pw_set_x_of f set (), 178
pw_set__xy_of f set (), 178
pw_set_ 3 r_of f set (), 178
pixwindebug, 230
prioritizer__func (), 81
prompt, see fullscreen
PW__F IXED_I MAGE, 21, 22
PW_INPUT_DEFAULT, 21, 22
PW_NO_LOC_AD JUST, 21, 22
Pw_pixel_cache (), 183
PW_PIXEL_CACHE_NULL, 183
-238-
Index — Continued
PW_REPAINT_ALL, 21, 22
PW_RETAIN, 21, 22
R
“raw” mode, 233
readv(2), 91
rect, 197, 31
coord type, 197
Rectlist, 197
rect and rectlist functions and macros
rect_bottom (), 197
rect_bounding (), 198
rect_clipvector (), 199
rect_construct (), 198
rect__equal (), 198
rect_includespoint (), 198
rect_includesrect(), 198
rect_intersection (), 198
rect_intersectsrect(), 198
rect_isnull (), 198
rect_marginadjust (), 198
rect__order (), 199
rect_passtochild (), 198
rect^passtoparent (), 198
rect_right (), 197
rl_boundintersectsrect (), 201
rl_coalesce (), 202
rl_coordoffset (), 200
rl_copy (), 202
rl_difference (), 202
rl_empty (), 201
rl__equal (), 201
rl_equalrect (), 201
rl_free (),202
rl_includespoint (), 201
rl_initwithrect (),202
rl__inter sect ion (), 202
rl_normalize (), 202
rl_null (),200
rl_passtochild (), 200
rl_passtoparent (), 200
rl_rectdifference (), 202
rl_rectintersection (), 202
rl_rectoffset 0,200
rl_rectunion (), 202
rl_sort (), 202
rl_union (), 202
Rect struct, 197
rect_null, 198
Rectlist, 199
rectnode, 200
RECTS__BOTTOMTOTOP, 199
RECTS_LEFTTORIGHT, 199
RE CT S__R IGHTT OLEF T, 199
RECTS_SORTS, 199
RE CT S_T OP TOBOT TOM, 199
RECTS_UNSORTED, 199
region
use for tiles, 21
rlimit(2), 91
root window
accessing the root fd, 50
s
scheduler_func (), 86
SCR_EAST, 50
SCR_NAMESIZE, 48, 57
SCR_NORTH, 50
SCR_POSITIONS, 50
SCR_SOUTH, 50
SCR_SWITCHBKGRDFRGRD, 48
SCR_WEST, 50
screen, 11,47,48, 56
adjacent, 50
creating, 48
destruction, 49
fullscreen access, see fullscreen
mouse, 56
multiple, 50
positions, 50
querying, 49
standard command-line argument parsing, 49
SCROLL_DEVID, 54
SCROLL_ENTER, 206
SCROLL_EXIT, 206
SCROLL_REQUEST, 207
scrollbar, 205
line-by-line scrolling, 211
scrolling, 208
updating, 206
scrollbar attributes
SCROLL_LAST_VI EW_START, 210
S CROLL_L I NE__HE IGHT, 211
SCROLL_MARGIN, 209
SCROLL_NORMALIZE, 209
S CROLL_NOTIFY_CL IENT, 205
SCROLL_OB JECT, 206, 210
SCROLL_OBJECT_LENGTH, 206, 210
SCROLL_REQUEST__MOT I ON, 210
SCROLL_REQUEST_OFFSET, 210
SCROLL_VI EW_LENGTH, 206, 210
SCROLL_VI EW_START, 209, 210
<suntool/scrollbar.h>, 205
selection callback procedures, 104, 97, 102
functionjproc, 105,113
replyjjroc, 113
reply_proc (), 106
selection client debugging
adjusting RPC timeouts, 109
dumping selection data, 109
running a test service, 109
service displays, 109
tracing request attributes, 123
selection library data types
Seln_function, 110
Seln_function__buffer, 105, 111
Seln_holder, 110
Seln_holders_all, 111
Seln_rank, 110
Seln_replier_data, 107, 111
Seln_request, 102, 111
Seln_requester, 102, 111
Seln_response, 105, 110
Seln_result, 110
Seln_state, 110
-239-
Index — Continued
selection library procedures
seln_acquire (), 104,112
seln_ask (), 103, 112
seln_clear_functions (), 112
seln_create (), 96, 98,112
seln_debug (), 113
seln_destroy (), 97, 113
seln_done(), 113
seln__dump_function_buf fer (), 113
seln_dump__function_key (), 114
seln_dump__holder (), 114
seln_dump_rank (), 114
seln_dump_response (), 114
seln_dump_result (), 114
seln_dump_service (), 114
seln_dump_state (), 115
seln__figure_response (), 105, 115
seln_functions_state (), 102, 115
seln_get_function_state (), 102, 115
seln__hold_file (), 109, 115
seln_holder_same_client (), 116
seln_holder_same_process (), 116
seln__inform (), 116
seln_init_request (), 103,117
seln_inquire (), 117,126
seln_inquire_all (), 117
seln_query (), 103, 118, 126
SELN__REPORT, 118
seln_report_event (), 102,116
seln_report_event()" M , 118
seln__request (), 103, 119
seln_same_holder (), 119
seln_secondary_exists (), 106, 119
seln_secondary_made (), 106, 119
seln_use_test_service (), 109, 119
seln_use_timeout (), 109, 120
seln_yield (), 104
seln_yield_all (), 120
selection request, 102, 95
buffer, 102
buffer size, 111
for non-held selection, 108
initiated by function-key, 104
long replies, 104, 108
read procedure, 103
replier context, 107
replying, 106
request attribute definitions, 103
requester context, 104
sample program, 104
unrecognized requests, 104, 108
selection request attributes, 121 thru 124
SELN_REQ_BYTESIZE, 122
SELN_REQ_COMMI T_PEND ING_DELETE, 106, 108, 123
SELN_REQ_CONTENTS_ASCII, 103, 122
SELN_REQ_CONTENTS_P IECES, 122
SELN_REQ_DELETE, 123
SELN_REQ_END_REQUEST, 107, 124
SELN_REQ_FAILED, 124
SE LN_RE Q_F AKE_LE VEL, 123
SE LN_RE Q_F I LE_N AME, 122
SELN_REQ_F IRS T, 122
SE LN_REQ_F I RST_UN IT, 122
SELN_REQ_LAST, 122
selection request attributes, continued
SELN_REQ_LAST_UN IT, 122
SELN_REQ_LEVEL, 122
SELN_REQ_RE STORE, 123
SELN_REQ_SET_LEVEL, 123
SELN__REQ_UNKNOWN, 124
SELN_REQ_UNRECOGNIZED, 104
SELN_REQ_YIELD, 106, 108, 123
selection response
SELN_DELETE, 106
SELN_FIND, 106
SELN_I GNORE, 105
SELN_REQUEST, 106
SELN_SHELVE, 106
Selection Service, 95,13
Selection Service
acquiring selections, 104
adjusting RPC timeouts, 109
callback procedures, 97,102,104,112
caret, 96
client, 96
clipboard, 96
common request attributes, 121
concepts, 96
consume-reply procedure, 103
data definitions, 110
debugging clients, see selection client debugging
enumerated types, 110
function key notifications and processing, 104
function key transitions, 101,105
getting the selection’s contents, 102
header files, 110
library, 95
overview, 96
Primary, 96
procedure declarations, 112
protocol example, 97
releasing selections, 104
replying to requests, 106
request, see selection request
request buffers, 102
required header files, 110
running a test service, 109
sample program, 104
sample program get_selection, 125
sample program seln_demo t 128
sample programs, 125
Secondary, 96
selection holder, 96
selection rank, 96
selection__svc (1) program, 97
sending requests to the selection holder, 102
server process, 95
shelf, 96
status display & tracing, 109
the selection itself, 96
timeouts, 109
tracing request attributes, 123
SELN_CARET, 110
SELN_CONT INUED, 110
SELN_DELETE, 110
selnjdemo example program, 128
SELN_D I DNT_HAVE, 110
240-
Index — Continued
SE LN_EX I ST S, 110
SELN_FAI LED, 110
SELN_FILE, 110
SELN_FIND, 110
SELN_FN_AGAIN, 110
SELN_FN_ERROR, 110
SELN_FN_FIND, 110
SELN_FN_FRONT, 110
SELN_FN_GET, 110
SELN_FN_OPEN, 110
SELN_FN_PROPS, 110
SE LN_FN_P UT, 110
SELN_FN_STOP, 110
SELN_FN_UNDO, 110
SELN_IGNORE, 110
SELN_LEVEL_ALL, 124
SELN_LEVEL_FIRST, 124
SELN_LEVEL_LINE, 124
SELN_LEVEL_NEXT, 124
SELN_LEVEL_PREVIOUS, 124
SELN_NON_EXIST, 110
SELN_NONE, 110
SELN_PRIMARY, 110
seln_*, see selection library procedures
SELN_REQ_*, see selection request attributes
SELN_REQUEST, 110
SELN_SECONDARY, 110
SELN_SHELF, 110
SELN_SHELVE, 110
SELN_SUCCESS, 110
SELN_TRACE_ACQUIRE, 123
SELN_TRACE_DONE, 123
SE LN_TRACE_HOLD_FILE, 123
SELN_TRACE_INFORM, 123
SELN_TRACE_INQUIRE, 123
SE LN_TRACE_S TOP, 123
SELN_TRACE_YIELD, 123
Seln_*, see selection library data types
SELNJJNKNOWN, 110
SELN_UNRECOGNIZED, 110
SELN_UNSPECIFIED, 110
SELN_WRONG_RAN, 110
SELN_WRONG_RANK, 110
set jmp(2), 91
setpriority(2), 91
setquota(2), 91
SIG_BIT, 81
SIGALRM, 83
sigblock(2), 91
SIGCHLD, 83
SIGIO, 39
SIGKILL, 49
sigmask(2), 91
signal(3), 232
signal handling, 232
signal(2), 90
signal(3), 91
sigpause(2), 91
sigstack(2), 91
SIGTERM, 49, 80
SIGTSTP, 232
SIGURG, 70
sigvec(2), 90, 91
SIGVTALRM, 83
SIGWINCH, 42,176,230
SIGXCPU, 34
singlecolor, 47
Sun View
abstractions/objects, 11
architecture, 7,12
changes from 2.0,3
compatibility with future releases, 3
environment usage, 42
introduction, 3
no more tool merging, 229
programming notes, 229
shared libraries, 229
system model, 11
what is supported, 229
SUNVIEWJDEVID, 54
system calls not to be used under SunView, 91
T
terminal emulation, 232
tile, 21,11
dynamically changing flags, 23
extracting data, 23
laying out, 22
notification from the Agent, 23
notifying tiles through the Agent, 24
overlap, 14
registering with the Agent, 21
removing from the Agent, 26
SunView 1 model, 14
tool
iconic flag, 40
parent, 42
TOP_DEVID, 54
TR_UNTRANS_EVENT, 56
TRUE, 197
tty(4), 232
u
umask(2), 91
UNIX and SunView, 232
UNIX system calls and SunView
close(2), 91
dup(2), 91
ioctl(2), 91
open(2), 29
readv(2), 91
rlimit(2), 91
select(2), 176
setitimer(2), 91
set jmp(2), 91
setpriority(2), 91
setquota(2), 91
sigblock(2), 91
sigmask(2), 91
-241-
Index — Continued
UNIX system calls and SunView, continued
signal(2), 90
signal(3), 91
sigpause(2), 91
sigstack(2), 91
sigvec(2), 90, 91
write(2), 91
y
Virtual User Input Device, see vuid
vuid, 53
adding a new segment, 55
choosing events, 217
device controls, 217
example code, 218
firm events, 215
input device control — see input device, 56
no missing keys, 55
pair, 216
result values, 55
sample device driver, 218
segments, 54
state, 55
station codes, 54
writing a vuid driver, 215
Vuid_addr_jprobe, 218
< sun dev/vuid__e vent. h>, 55, 215,218
VUIDFIRMEVENT, 217
VUID NATIVE, 217
VUID_SEG_SIZE, 54
VUIDGADDR, 218
VUIDGFORMAT, 217
VUIDSADDR, 218
VUIDSFORMAT, 217
w
we_getgfxwindow (), 41
we_getparentwindow (), 43
we_setgfxwindow (), 41
we_setparentwindow(), 42
when_hint, 77
WIN ioctl number error, 43, 230
win__bell (), 37
win_compu tec lipping (), 192
win_copy_event (), 25
<sunwindow/win_enum.h>, 35
win__enum_input_device (), 58
win_enumerate_children (), 35
win_enumerate_subtree (), 35
win__error (), 43
win__errorhandler (), 43
win__f dtoname (), 30
win_fdtonumber(), 31
win_findintersect(), 41
win_free_event (), 25
win_get_designee (), 39
win_get_event_timeout (), 61
win__get_f d (), 23
win_get__f lags (), 23
win_get_focus_event (), 59
win_get_kbd_focus (), 58
win_get_kbd_mask (), 39
win_get_pick_mask (), 39
win_get_pixwin (), 23
win_get_swallow_event (), 59
win_get_tree_layer (), 36
win_get__vuid__value (), 55
win_getheight (), 31
win_getinputcodebit(), 38
win__getlink (), 33
win_getnewwindow (), 29
win_getowner (), 42
win_getrect (), 31
win_getsavedrect (), 32
win_getscreenpositions (), 50
win__getsize (), 31
win_getuserflags (),40
win_getwidth (), 31
win_grabio (), 182
win_grabiodebug, 230
win_init screenf romargv (), 49
<sunwindow/win_input.h>, 55
win_insert(), 33
win_insertblanket(), 41
win_is_input_device (), 57
win_isblanket (), 42
win_lockdata (), 34, 190
win_lockdatadebug, 230
WIN__NAMESIZE, 30
win_nametonumber(), 30
win_nextfree(), 30
WIN_NULLLINK, 30, 32
win_numbertoname (), 30
win^partialrepair (), 192
win_j?ost_event (), 25
win_post_event_arg (), 25
win_jpost_id (), 24
win_j?ost_id_and_arg (), 25
win_refuse_kbd_focus, 58
win_register (), 21
win_release_event_lock (), 60
win__releaseio (), 182
win_remove (), 34
win_remove_input_device (), 57
win__removeblanket (), 42
win_screendestroy (), 49
win_s creenget (), 49
win_screennew (), 48
win_set_designee (), 39
win_set__event_timeout (), 61
win_set_flags (), 23
win_set_focus_event (), 59
win__set__input_device (), 57
win_set_kbd_focus (), 58
win_set_kbd_mask (), 39
win_set_pick__mask (), 39
win_set_swallow__event (), 59
win_setinputcodebit(), 38
242-
Index — Continued
win__setkbd (), 56
win_setlink (), 33
win_setmouseposition (), 40
win_setms (), 56
win__setowner (), 42
win_setrect(), 31
win_setsavedrect (), 32
win_setscreenpositions (), 50
win__setuserf lag (), 40
win_setuserf lags (), 40
win_un lock data (), 34, 190
win_unregister (), 26
win_un set input codebit (), 38
window, 29, 11
activation, 33
as device, 29
as screen, 47
blanket, 41
blanket flag, 40
clipping, 14
creation, 29
cursor tracking, 15
data, 14
data lock, 34
database locking, 16
decoding error messages, 43
destruction, 29
device, 13
display tree, 14, 32
enumerating offspring, 35
enumerating the window tree, 36
enumeration, 35
environment usage, 41
errors, 43
geometry, 31
hierarchy, see window — display tree
iconic flag, 40
identifier conversion, 30
input, 37
input events, 15
locate window, 41
mouse position, 40
naive programs, 41
name, 30
new, 29
next available, 30
null, 30
number, 30
owner, 29,42
parent, 31
position, 14, 31
querying size, 31
reference, 29
referencing, 30
saved rect, 32
screen information, 49
SIGWINCH, 42
user data, 40
user flags, 40
window driver, 13
window attributes
WIN_FD, 29
window device layer, 7
window display tree
SIGXCPU deadlock resolution, 34
batched updates, 34
insertion, 33
links, 32
removal, 34
window functions and macros
window_create, 232
window_main__loop (), 85
window management, 189
minimal repaint, 192
WINDOW__GFX, 41
Window_handle, 35
WINDOW_PARENT, 42
windowfd, 30
WL_BOTTOMCHILD, 32
WL_COVERED, 32
WL_COVERING, 32
WL_ENCLOSING, 32
WL_OLDERSIB, 32
WL__OLDE ST CHILD, 32
WL_PARENT, 32
WLJTOPCHILD, 32
WL_YOUNGERSIB, 32
WL_YOUNGESTCHILD, 32
wmgr_bottom (), 189
wmgr_changelevel (), 191
wmgr_changerect(), 189
wmgr__close (), 189
wmgr_completechangerect(), 190
wmgr_confirm(), 190
wmgr_forktool (), 190
wmgr_getrectalloc (), 192
WMGR_I CONIC, 191
wmgr_iswindowopen (),191
wmgremove (), 189
wmgr_open (), 189
wmgr_ref reshwindow (), 189
wmgr_setrectalloc (), 192
wmgr_stretch (), 189
wmgr_top (), 189
wmgr_winandchildrenexposed (), 191
workstation, 53,11
WORKSTATI ON_DEVI D, 55, 216
write(2), 91
ws_* variables, see kernel tuning
w s__u s r_a s yn c, 63
WUFJWMGR1, 191
243-
Notes
Notes
Notes
Notes
Notes
0
c
i*
Introduction
Introduction.
What is SunView?.
Release 3.0.
Release 3.2.
Release 3.4.
Release 3.5.
Release 4.0.
On-Line Help ...
Code No Longer Supported ...
3
3
4
4
4
4
4
4
5
5
What is SunView?
Introduction
SunView (Sun Visual/Integrated Environment for Workstations) is a user-
interface toolkit to support interactive, graphics-based applications running
within windows. It consists of two major areas of functionality: building blocks
for output, and a run-time system for managing input. The building blocks
include four types of windows:
□ canvases on which programs can draw,
□ text subwindows with built in editing capabilities,
□ panels containing items such as buttons, choice items, and analog sliders,
□ tty subwindows in which programs can be run.
Canvases, text subwindows, and panels can be scrolled.
These windows are arranged as subwindows within frames, which are themselves
windows. Frames can be transitory or permanent.
Transient interactions with the user can also take place in menus which can
“pop-up” anywhere on the screen, and in alerts.
The run-time system is based on a central Notifier in each application which dis¬
tributes input to the appropriate window, and a window manager which manages
overlapping windows, distributing to the appropriate application.
The exchange of data between applications running in separate windows (in the
same or separate processes) is facilitated by a Selection Service.
The Sun implementations of graphics standards — CGI, CORE, GKS — include
extensions to run within windows. See the SunCGI Reference Manual, the Sun-
Core Reference Manual, and the SunGKS manual, respectively, for more infor¬
mation.
3
Revision A, of May 9,1988
4 Sun View 1 Programmer’s Guide
History
Release 3.0
Release 3.2
Release 3.4
Release 3.5
Release 4.0
SunView first appeared in SunOS Release 3.0. It is an extension and refinement
of SunWindows 2.0, containing many enhancements, bug fixes and new facilities
not present in SunWindows. SunView is upward compatible with SunWindows
— applications originally written under 2.0 can be recompiled and run under
SunView.
In Release 3.0, these changes were reflected in a new organization for the Sun¬
View documentation. The material on Pixrects from the 2.0 SunWindows Refer¬
ence Manual was broken out into a separate document, the Pixrect Reference
Manual. Two new documents were introduced, the SunView Programmer’s
Guide and the SunView System Programmer’s Guide.
The basic SunView interface, intended to meet the needs of simple and
moderately complex applications, is documented here. This basic interface cov¬
ers the functionality of the SunWindows window and tool layers.
The companion to this document is the SunView System Programmer’s Guide.
Its contents are a combination of new and old material. Several of its chapters
document new facilities such as the Notifier, the Selection Service and the
Defaults Package. Also included is material from the old SunWindows Reference
Manual which is of interest to implementors of window managers and other
advanced applications, such as the window manager routines.
Many bug fixes and performance improvements were made to SunView for
Release 3.2. This guide was extensively revised and added to for Release 3.2.
Further bug fixes and enhancements came out with Release 3.4. These were
documented in the Release 3.4 Manual.
Release 3.5 brought support for hardware double-buffering under SunView and
pixrects.
Release 4.0 brings major enhancements to the SunView user interface — ‘Search
and Replace’ in text subwindows, shadowed frames, ‘Props’ frame menu item,
keyboard control of the caret, etc. — without involving major changes to its pro¬
grammatic interface. For example, when programs that use text subwindows are
recompiled, their users will be able to use the new ‘Select Marked Text’ pop-up
frame. The alerts package is a new package for presenting information to the
user and allowing him/her to make choices based on it.
This guide was revised and reprinted again for 4.0. The major changes are the
addition of a new Alerts chapter and lists of attributes and functions at the begin¬
ning of some chapters as well as in the SunView Interface Summary chapter and
Index.
microsystems
Revision A, of May 9, 1988
Chapter 1 — Introduction 5
On-Line Help For information on the programmatic interface to the on-line help facilities of the
Sun386i, see the Sun386i Developer’s Guide. The spot help interface will be
supported on all Sun woricstations in the next release of SunView.
Code No Longer Supported Do not use DEFINE_IC0N_FR0M_IMAGE or
DEFlNE_CURSOR_FROM_lMAGE as these macros may not be supported in
future releases. Instead, use icon_create () and cursor_create () to
create the icon or cursor at runtime. icon_create () is described in Chapter
14, Icons. cursor_create () is described in Chapter 13, Cursors.
The old SunWindows stacking menu package has been supplanted by the Sun-
View walking menu package, described in Chapter 12 of this document. You
should convert your applications to use the menu package, as the old package
may not be included in future releases.
The new alerts package, described in Chapter 10, replaces use of the old (undo¬
cumented) menu_prompt () routine in situations where programs want to
force the user to acknowledge a message or make a choice. Alerts are more flexi¬
ble and easy-to-use than menu_prompt (), and we strongly encourage you to
convert to them. Again, the old package may not be included in future releases.
microsystems
Revision A, of May 9, 1988
The Sun View Model
The Sun View Model. 9
2.1. Objects. 9
Window Objects. 11
Other Visual Objects. 11
2.2. Examples of the use of Objects by Applications. 12
2.3. Windows. 16
Frames . 16
Manipulating Frames Via Menus. 18
Subwindows. 19
2.4. Input: The Notifier. 20
Callback Style of Programming. 20
Why a Notification-Based System?. 22
Relationship Between the Notifier, Objects, and the
Application. 22
Calling the Notifier Directly. 24
The Sun View Model
This chapter introduces the conceptual model presented by SunView, covering
such basic concepts as objects, windows and the Notifier.
It is important that you understand the material in this chapter before you begin
to write SunView applications.
2.1. Objects
SunView is an object-oriented system. Think of SunView objects as visual
building blocks which you use to assemble the user interface to your application.
Different types of objects are provided, each with its particular properties; you
employ whatever type of object you need for the task at hand.
The most important class of SunView objects are windows. Not all objects are
windows, however. Other visual objects include cursors, icons, menus and
scrollbars.
Technically, an object is a software entity presenting a functional interface. The
implementation of the object is not exposed; you manipulate an object by passing
its unique identifier, or handle, to its associated functions. The style of program¬
matic interface resulting from this object-oriented approach is outlined in this
Chapter.
Figure 2-1 illustrates the different types and classes of SunView objects:
9
Revision A, of May 9, 1988
10 SunView 1 Programmer’s Guide
The different types of objects are shown in normal font; the classes to which the
objects belong are labeled in italics — Subwindow, Window, and Object.
Each object type is described briefly on the next page.
#sun
xr microsystems
Revision A, of May 9, 1988
Chapter 2 — The SunView Model 11
Window Objects
Other Visual Objects
Window objects include frames and subwindows. Frames contain non¬
overlapping subwindows 2 within their borders. Currently, there are four types of
subwindows provided by SunView:
□ Panel Subwindow — A subwindow containing panel items.
□ Text Subwindow — A subwindow containing text.
a Canvas Subwindow — A subwindow into which programs can draw.
□ TTY Subwindow — a terminal emulator, in which commands can be given
and programs executed.
The distinctions between frames and subwindows are explained in more detail in
Section 2.3, Windows, later in this chapter.
The other types of objects, like windows, are displayed on the screen, but they
differ from windows in that they are less general and more tailored to their
specific function. They include:
□ Panel Item — A component of a panel that facilitates a particular type of
interaction between the user and the application. Panel items can be moved,
displayed or undisplayed under program control. There are several
predefined types of items, including buttons, message items, choice items,
text items and sliders.
□ Scrollbar — An object attached to and displayed within a subwindow
through which a user can control which portion of the subwindow’s contents
are displayed. Both vertical and horizontal scrollbars can be attached to
panels and canvases. Text subwindows contain vertical scrollbars by default
(they cannot contain horizontal scrollbars).
□ Menu — An object through which a user makes choices and issues com¬
mands. By convention in SunView, menus pop up when the user presses the
right mouse button. Like windows, menus appear on the screen when
needed, and disappear when they have served their purpose. Menus, how¬
ever, differ from windows in several ways. First, they are more ephemeral
— a menu only remains on the screen as long as the menu button remains
depressed, 3 in contrast to a window, which remains on the screen until the
user indicates he is done or the controlling program explicitly undisplays it.
Second, menus are less flexible than windows; they are designed specifically
to allow the user to choose from among a list of actions.
~ |c«»r UV.orJ.ihg
2 It is SunView’s window layout policy that enforces non-overlapping subwindows, not some limitation of
the system. If you access the window system at a very low level, subwindows can overlap successfully.
3 The one exception is in the case of stay-up menus, which will appear when you click the RIGHT mouse
button and disappear when you click it again.
microsystems
Revision A, of May 9, 1988
12 SunView 1 Programmer’s Guide
□ Alert —a box on the screen which informs the user of some condition. It
has one or more buttons which the user can push to dismiss the alert or
choose a means of continuing. Like menus, alerts are ephemeral — they
disappear as soon as the user pushes a button or otherwise dismisses the
alert. Visually, they resemble simple panels containing only images, mes¬
sages, and buttons.
□ Pointer — The object indicating the mouse location on the screen.
□ Icon — a small (usually 64 x 64 pixel) image representing the application.
The next section gives some examples showing how typical applications make
use of SunView objects in their user interface.
2.2. Examples of the use of Figure 2-2 illustrates the mailtool(l), which uses SunView objects to provide
Objects by a mouse-oriented interface to the SunOS mail(l) program:
Applications
Figure 2-2 Mailtool
Pfthidt
inkj —-
T'iL
microsystems
Revision A, of May 9,1988
Chapter 2 — The SunView Model 13
Mailtool consists of a frame containing three subwindows: a text subwindow in
which the message headers are displayed, a panel containing various panel items
(mostly buttons) through which the user can give commands to mail, and a text
subwindow which displays the current message. An additional text subwindow
and panel (shown in the figure) appear when you press the reply or compose but¬
tons.
The text subwindows contain scrollbars, allowing the user to bring more infor¬
mation into view.
Figure 2-3 illustrates iconedit(l), a simple bitmap editor for generating
images to be used by SunView applications:
Figure 2-3 iconedit
par-li/
C a ^ v 0^
.jv'Wt
iconedit consists of a frame and five subwindows. From upper left to lower
right they are:
□ a panel containing instructions on how to use the mouse;
o a small panel for short messages:
□ a canvas for drawing the image;
□ a panel containing various items for issuing commands and setting options
such as the size of the image being drawn, the drawing mode, etc;
□ A small canvas for viewing the icon or cursor actual size.
microsystems
Revision A, of May 9, 1988
14 SunView 1 Programmer’s Guide
None of these subwindows may be scrolled.
In Figure 2-4, the user has pushed the New Mail button, and the program brings
up a hour glass cursor (in the upper right of the text subwindow) to denote that it
is retrieving mail:
Figure 2-4 iconedit-buttons
committing changes and retrieving new mail
1 root@sun.com
2 root@sun.com
3 spage@polar
4 tjacobs@snouking
5 sages@pages
6 root@sun.com
7 root@sun.com
8 spage@omega
Mon Dec
Sat Dec
Frl Dec
Tue Dec
7 03:ZB
5 03:15
4 15:23
1 10:40
Tue Nov 10 15:41
Mon Oct 19 22:19
Tue Oct 20 22:21
Tue Oct 20 13:02
35/1942 Teen nail
117/3087 Tech Mall
43/1516 what size to Import scrol
40/1816 Casting
70/2177 Re: new textsw feature
55/1671 Tech Mall
141/4393 Tech Mall
36/1354 Re: Name completion & cmd
[ Show ")[ Next ")[ Delete j[ Reply j[ComposF)
[ Save )[ Folder j Flle: +yb1nfo
[ Mlsc ] [ Coni )
I from rootisnall (ion fict 19 22:19:17 1987
Return-Path: <root@sna11> ]
Received: from snal 1 .sun.t:om by zorba.sun.com (3.2/SMI-3.2)
Id AA19735; Mon, 19 Oct 87 22:19:13 PDT
I Received: by sna11.sun.com (4.0/SMI-3.2)
Id AA02077; Tue, 20 Oct 87 03:00:09 PDT
Date: Tue, 20 Oct 87 03:00:09 PDT
Message-Id: <8710201000.AA02077@sna11.sun.com>
From: root@sun.com
Subject: Tech Mall
Apparently-To: tech-list
Status: RO
Sun Tech Mall for Tue Oct 20 03:00:04 PDT 1987
Requests to receive tech mall should be sent to al1ases@sun. ***
**** Items you wish to post to tech should be sent to tech@sun. ****
I Today's Topics:
mh wizards, anyone?
console window problem
Date: Mon, 19 Oct 87 14:54:11 PDT
From: now1ck1@speed (Bill Nowlckl)
Subject: mh wizards, anyone?
I have heard that a feature I added to sendmall for 4.0 causes mh
to break. I don't use mh, so could someone who knows what It Is
doing please get In touch with me? I have a feeling It Is using the -t
msun
xr microsystems
Revision A, of May 9, 1988
Chapter 2 — The SunView Model 15
In Figure 2-5, the user has pressed the mouse button over the Folder panel button
in the panel:
Figure 2-5 iconedit-menus
1 rootSsurTcan^^
2 rootfisun.cam
Mon Dec
Sat Dec
7 03:26
5 03:15
55/1942
117/3087
3 spage0polar
Frl Dec
4 15:23
43/1516
4 tjacobsSsnouking
Tue Dec
1 10:40
40/1816
5 sagesSpages
Tue Nov
10 15:41
70/2177
6 rootdsun.com
Mon Oct
19 22:19
55/1671
7 root0sun.com
Tue Oct
20 22:21
141/4393
8 8page0amsga
Tue Oct
20 13:02
36/1354
Tech Mall
Tech Mall
what size to import scrol
Casting
Re: neu textsw feature
Tech Mail
Tech Mail
Re: Name completion & and
f Shout ~)[ Next ][ Delete Reply ][Compose]
[ Save ][ Foldej ♦ecpspec
♦SVDOC
♦SVMN
♦Teral no logy
♦bugs
♦ laff
♦Motiflor
♦sunvlew
♦terminology/*
♦wnogat
♦ybinfo
f Print ~){Heui Hail]
f Mlsc H "t»one )
From rootftsnaif
Return-Path: <|
Received: froi
Id AAll,
Received: by snail.sun.can (4.0/SMI-3.2;
Id AA02077 ; Tue, 20 Oct 07 03:00:09 PDT
Date: Tue, 20 Oct 07 03:00:09 PDT
Message-Id: <8710201000.AA02077esna11.sun.con>
Fran: rootesun.com
Subject: Tech Mall
Apparently-To: tech-list
Status: RO
Sun Tech Mall for Tue Oct 20 03:00:04 POT 1987
’ Requests to receive tech mall should be sent to allasesQsun.
* Items you wish to post to tech should be sent to techCsun. •••'
Today's Topics:
mh wizards, anyone?
console window problem
Date: Mon, 19 Oct 97 14:54:11 PDT
From: now1ck18speed (8111 Nowlcklj
Subject: mh wizards, anyone?
I have heard that a feature I added to sencknall for 4.0 causes mh
to break. I don't use mh, so could someone who knows what It Is
doing please get In touch with me? I have a feeling it Is using the -t
mail tool has displayed a pop-up menu showing names of files which the user
can insert into the text item File: by selecting a file. The purpose of this menu is
to keep a current record of the mailfiles that the user has.
Revision A, of May 9, 1988
16 SunView 1 Programmer’s Guide
2.3. Windows
Frames
There are two basic classes of windows in SunView: overlapping frames, which
contain non-overlapping subwindows. This section describes the distinction
between the two.
A frame is not useful in itself — its purpose is to bring subwindows of different
types together into a common framework so they can be operated on as a unit. A
frame is said to own the subwindows it contains.
Frames may also own other frames. Thus the basic SunView structure is a
hierarchy of windows. It could also be viewed as a tree of windows in which the
non-leaf nodes are frames and the leaf nodes are subwindows.
The frame at the top of the hierarchy will be referred to in this document as the
base frame, other frames will be referred to as subframes . 4 Subframes are typi¬
cally used to implement pop-ups, which perform auxiliary functions such as
allowing the user to set options, or displaying help text. 5
iconedit uses a pop-up for browsing images. When the user presses the but¬
ton labeled Browse, iconedit displays a pop-up which consists of a subframe
containing a single panel subwindow.
Figure 2-6 illustrates iconedit with its pop-up displayed.
Figure 2-6 A subframe
4 Note that while an application will usually be implemented as a single base frame (and its subwindows and
subframes), it could well include several base frames.
5 For details on pop-ups, see Section 4.5.1, Pop-ups, in Chapter 4, Using Windows.
Revision A, of May 9, 1988
Chapter 2 — The SunView Model 17
Figure 2-7 and Figure 2-8 illustrate the structures of iconedit and mail-
tool as a tree of windows. Frames are shown as rectangles; subwindows as cir¬
cles:
Figure 2-7 Structure of iconedit
Figure 2-8 Structure ofmailtool
Revision A, of May 9, 1988
18 SunView 1 Programmer’s Guide
Manipulating Frames Via Frames may be manipulated programmatically by setting the frame’s attributes,
Menus as described in Chapter 4, Using Windows . Each frame also has a menu which
allows the user to manipulate the frame directly. The frame menu is invoked by
pressing the RIGHT mouse button on the exposed parts of the frame, which
include the double lines surrounding the subwindows and the black frame header
which usually appears at the top of the frame.
The menus for base frames and subframes differ slightly, as you can see from
Figure 2-9 and Figure 2-10. The first window shows the base frame menu; the
second window shows the subframe menu:
Figure 2-9 Base frame menu
Revision A, of May 9, 1988
Chapter 2 — The SunView Model 19
Figure 2-10 Subframe menu
l
Raslza *
Front
•ack
Props
kodlsplay
Subwindows
Both menus contain the ‘Move’, ‘Resize’, ‘Front’, ‘Back’, and ‘Redisplay’ com¬
mands. ‘Move’ allows the user to change the frame’s location. ‘Resize’ allows
him or her to change the window’s width and height. ‘Front’ causes the frame to
move in front of the other windows, becoming fully visible on the “surface” of
the screen, while ‘Back’ does the opposite, moving the frame behind any other
windows occupying the same portion of the screen. ‘Redisplay’ simply causes
the window to be displayed again.
When the user is finished working with a base frame he may want to destroy it
for good, in which case he would choose ‘Quit’. Or he may want to ‘Close’ the
frame, with the anticipation of opening it later and continuing work where he left
off. A base frame in its closed state is represented on the screen as a small (usu¬
ally 64 by 64 pixel) icon. The icon is typically a picture indicating the function
of the underlying application.
Subframes may not be closed into icons; when the user finishes with a subframe,
he simply chooses Done from the menu. While not destroying the subframe, this
causes it to disappear from the screen.
Subwindows differ from frames in several basic ways. Subwindows never exist
independently. They are always owned by a frame, and may not themselves own
subwindows or subframes. While frames can be moved freely around the screen,
subwindows are constrained to fit within the borders of the frame to which they
belong. Also in contrast to frames, subwindows are tiled —they may not over¬
lap each other within their frame. Within these constraints (which are enforced
by a run-time boundary manager) subwindows may be moved and resized by
either a program or a user.
So far this chapter has discussed the static aspects of the SunView model. The
section below outlines the system’s model from a dynamic point of view.
Revision A, of May 9, 1988
20 SunView 1 Programmer's Guide
2.4. Input: The Notifier SunView is a notification-based system. The Notifler acts as the controlling
entity within a user process, reading UNIX input from the kernel, and formatting
it into higher-level events, which it distributes to the different SunView objects. 6
Callback Style of Programming In the conventional style of interactive programming, the main control loop
resides in the application. An editor, for example, will read a character, take
some action based on the character, then read the next character, and so on.
When a character is received that represents the user’s request to quit, the pro¬
gram exits. Figure 2-11 illustrates this approach:
Figure 2-11 Flow of Control in a Conventional Program
start
end
Notification-based systems invert this “straight line” control structure. The main
control loop resides in the Notifier, not the application. The Notifier reads events
and notifies, or calls out to, various procedures which the application has previ¬
ously registered with the Notifier. These procedures are called notify procs or
callback procs. This control structure is shown in Figure 2-12.
6 SunView events are in a form which you can easily use: an ascii key has been pressed, a mouse button has
been pressed or released, the mouse has moved, the mouse has entered or exited a window, etc. Events are
described in detail in in Chapter 6, Handling Input.
Revision A, of May 9,1988
Chapter 2 — The SunView Model 21
Figure 2-12 Flow of Control in a Notifier-based Program
Revision A, of May 9,1988
22 SunView 1 Programmer’s Guide
Why a Notification-Based
System?
Relationship Between the
Notifier, Objects, and the
Application
For programmers who are not used to it, this callback style of programming takes
some getting used to. Its big advantage is that it takes over the burden of manag¬
ing a complex, event-driven environment. In SunView, an application typically
has many objects. In the absence of a centralized notifier, each application must
be responsible for detecting and dispatching events to all the objects in the pro¬
cess. With a centralized Notifier, each component of an application receives only
the events the user has directed towards it.
It is not necessary for you to interact with the Notifier directly in your applica¬
tion. SunView has a two-tiered scheme in which the packages that support the
various objects — panels, canvases, scrollbars, etc. — interact with the Notifier
directly, registering their own callback procedures. The application, in turn,
registers its own callback procedures with the object
Typically, when writing a SunView application you first create the various win¬
dows and other objects you need for your interface, and register your callback
procedures with the objects. Then you pass control to the Notifier. The work is
done in the various callback procedures.
Let’s illustrate the relationship of the Notifier, the SunView objects and the
application by taking iconedit as an example. Figure 2-13 illustrates how the
Notifier receives UNIX input and calls back to iconedit ’s subwindows, which
in turn call back to procedures supplied by iconedit.
microsystems
Revision A, of May 9, 1988
CO 3 Q ^ O 03 4— 0 £Zj
Chapter 2 — The SunView Model 23
Figure 2-13 Flow of Input Events in iconedit, a SunView Application
user types, moves mouse,presses mouse buttons...
\ l /
UNIX events: input on file descriptors
microsystems
Revision A, of May 9,1988
24 SunView 1 Programmer’s Guide
The main point of the diagram on the preceding page is to make clear the
double-tiered callback scheme. How you register the callback procedures will be
explained in the chapters on panels and canvases.
One point worth mentioning is the distinction between the “event procedures” for
the canvases and the “notify procedures” for the panel items. They are all call¬
back procedures, but they have different purposes. The canvas’s event procedure
doesn’t do much work— basically it calls out to the application’s event pro¬
cedure each time an event is received. The application sees every event and is
free to interpret the events however it likes.
The event procedure for panels, on the other hand, does quite a bit of processing.
It determines which item should receive the event, and places its own interpreta¬
tion on events — the middle mouse button is ignored, left mouse button down
over an item is interpreted as a “tentative” activation of the item, etc. It does not
call back to the notify procedure for the item until it receives a left mouse button
up over the item. So panel item notify procedures are not so much concerned
with the event which caused them to be called, but with the fact that the button
was pushed, or a new choice made, etc.
Calling the Notifier Directly As mentioned previously, for many applications you will not need to call or be
called by the Notifier directly — the Notifier calls back to the subwindows,
which in turn call back to your application.
However, if you need to use signals, or be notified of the death of a child process
which you have spawned, you do need to call the Notifier directly.
The Notifier also provides calls which allow you to insert your own routine in the
event stream ahead of a window. This technique is known as interposition.
When and how to call the Notifier directly is covered in Chapter 17, The Notifier.
microsystems
Revision A, of May 9, 1988
Interface Outline
Interface Outline. 27
SunView Libraries . 27
Compiling SunView Programs. 27
Header Files. 27
Object Handles. 28
Attribute-based Functions. 28
Standard Functions . 29
Example of SunView-Style Programming. 29
Attribute List Size. 29
Reserved Namespaces. 30
3
Interface Outline
This chapter outlines the SunView interface, the SunView libraries, header files,
object handles, attributes and the standard functions applicable to objects of each
type.
SunView Libraries The SunView functions that an application calls are mostly in the library file
/usr/lib/libsuntool. a if you are using the archive libraries and
/usr/lib/libsuntool. so if you are using the shared libraries. These
libraries include the code to create and manipulate high-level objects such as
frames, panels, scrollbars and icons. These packages in turn call routines in
/usr/lib/libsunwindow.a or/usr/lib/libsunwindow.so to
create and manipulate windows and interact with the Notifier. These in turn call
routines in /usr/lib/libpixrect. a or /usr/lib/libpixrect. so
that do the drawing on the screen.
NOTE Shared libraries are introduced in 4.0. The main benefit to using shared libraries
is that the executables are much smaller (for example, 24K instead of 1Mb for
textedit alone) because the libraries are loaded dynamically at runtime and are
subsequently shared by other executables. Additionally, when the shared
libraries are recompiled, new functionality is added, or bug fixes are made, the
client applications don’t need to be recompiled and linked unless the . so or an
interface changed. For more information on shared libraries, see Programming
Utilities and Libraries.
Compiling SunView Programs To compile a SunView program you must link in these three libraries, and,
because they are built one on top of another, their order is important. For exam¬
ple, to compile a typical SunView application whose source is myprog. c, you
would type in the command:
Header Files The basic definitions needed by a SunView application — covering windows,
frames, menus, icons and cursors — are obtained by including the header file
<suntool/sunview. h>. Definitions for the other types of object are found
in their own include files — <suntool/canvas .h>, <suntool/text .h>,
<suntool/panel. h>, etc.
27
Revision A, of May 9,1988
28 SvmView 1 Programmer’s Guide
Object Handles When you create a SunView object, the creation function returns a handle for the
object. Later, when you wish to manipulate the object or inquire about its state,
you pass its handle to the appropriate function. This reliance on object handles is
a way of information-hiding. The handles are opaque in the sense that you can’t
“see through” them to the actual data structure which represents the object.
Each object type has a corresponding type of handle. The window types of
Frame, Canvas, Textsw, Tty and Panel are grouped under the type Win¬
dow. So, for example, you can declare a panel as either a Panel or a Window,
whichever is most appropriate. The other object types are Panel_item, Menu,
Scrollbar, Cursor, and Icon.
Since C doesn’t have an opaque type, all the opaque data types mentioned
above are typedef’d to the UNIX type caddr_t (for “character address
type”), which in turn is typedef’d to char *.
In addition to the opaque data types, there are several typedef s which refer
not to pointers but to structs: Event, Pixf ont, Pixrect, Pixwin, Rect,
and Rectlist. Generally pointers to these structs are passed to SunView func¬
tions, so they are declared as Event *, Pixwin *, etc. The reason that the
is not included in the typedef is that the structs are publicly available, in
contrast to the object handles, which include the and which refer to structs
that are not publicly available.
The SunView data types are summarized in the table beginning on page 324 in
Chapter 19, SunView Interface Summary.
Attribute-based Functions A model such as that used by SunView, which is based on complex and flexible
objects, presents the problem of how the client is to manipulate the objects. The
basic idea behind the Sim View interface is to present a small number of func¬
tions, which take as arguments a large set of attributes.
For a given call to create or modify an object, only a subset of the set of all appli¬
cable attributes will be of interest. So that only the relevant attributes need be
mentioned, SunView functions make use of variable-length attribute lists. An
attribute list consists of attribute/value pairs, separated by commas, and ending
with a zero.
Each type of object has its own set of attributes. The attributes have prefixes
which indicate die type of object they apply to, i.e. FRAME_*, TEXTSW_*,
CANVAS_*, TTY_*, PANEL_*, MENU_*, CURSOR_*, ICON_*, SCROLL_*,
etc.
In addition to the sets of attributes applying to each type of object, there is a set
of window attributes of the form WIN_* which apply to all window objects.
These are attributes such as WIN_HEIGHT and WIN_WIDTH, which apply to all
windows regardless of whether they happen to be panels, canvases, etc.
microsystems
Revision A, of May 9, 1988
Chapter 3 — Interface Outline 29
Standard Functions
Example of Sun View-Style
Programming
For objects of all types there is a set of standard functions to create and destroy
the object and to get and set the object’s attributes.
Window functions are prefixed with window_, yielding
□ window_create(),
□ window_get(),
□ window_set (), and
a window_destroy().
Providing common window functions reduces the complexity of the interface.
Non-window functions are prefixed with the name of the object. So, to take
menus as an example, the standard functions are
□ menu_create(),
□ menu_get(),
□ menu_set(), and
□ menu_destroy().
The flavor of the interface is illustrated with the following code fragment, which
creates a scrollbar with a width of 10 pixels and a black bubble. Later, the
scrollbar’s width is changed to 20 pixels. Finally, the scrollbar is destroyed:
\
Scrollbar bar;
bar = scrollbar_create (SCROLL__WIDTH, 10,
SCROLL BAR COLOR,
SCROLL_BLACK,
0);
scrollbar_set(bar, SCROLL_WIDTH,
20, 0);
scrollbar_destroy(bar);
J
Note the zero which terminates the attribute lists in the *_create () and
*_set () calls. The most common mistake in using attribute lists is to forget
the final zero. This will not be flagged by the compiler as an error, however, it
will cause SunView to generate a run-time error message.
Attribute List Size As you can see from the example above, you can specify several attributes in a
single create () orset() call. The maximum length of attribute lists in Sun-
View is 250; see Maximum Attribute List Size in Chapter 18, Attribute Utilities.
Revision A, of May 9, 1988
30 SunView 1 Programmer’s Guide
Reserved Namespaces SunView reserves names beginning with the object types, as well as certain other
prefixes, for its own use.
The prefixes listed below should not be used by applications in lower, upper, or
mixed case.
Table 3-1 Reserved Prefixes
ACTION_
icon_
scroll_
alert_
menu_
seln_
attr_
notify_
textsw_
canvas_
panel_
text_
cursor_
pixrect_
toolsw_
defaults_
pixwin_
tool_
e i_
P r _
ttysw_
es_
pw
tty_
event_
rect_
window_
ev_
rl_
win_
frame_
help
scrollbar_
wmgr_
Revision A, of May 9,1988
Using Windows
Using Windows
33
4.1. Basic Routines.
Creating a Window.
Initiating Event Processing.
Modifying and Retrieving Window Attributes
Destroying Windows.
4.2. Example 1— helio world .
4.3. Example 2— simple_panel .
Some Frame Attributes.
Panels.
Fonts.
Panel Items.
Notify Procedure.
Window Sizing — window_f it ()
Fitting Frames Around Subwindows
4.4. Example 3— lister .
4.5. Example 4— filer .
Pop-ups .
Pop-up Text Subwindow.
Pop-up Property Sheet.
Invoking the ‘Props’ Menu Item
WIN_SHOW .
Pop-up Confirmer.
35
35
35
35
36
37
39
40
41
41
41
41
41
41
42
44
45
45
46
46
47
47
window_loop . 48
Restrictions on Pop-Up Frames. 49
Controlling a Pop-up or Frame’s Shadowing. 49
4.6. Example 5— image_browser_l . 50
Specifying Subwindow Size. 50
Default Subwindow Layout. 51
Explicit Subwindow Layout. 51
Specifying Subwindow Sizes and Positions. 52
Changing Sub window Layout Dynamically. 52
The Rect Structure . 52
4.7. Example 6— image_browser_2 . 53
Row/Column Space. 53
4.8. Attribute Ordering. 55
Different Classes of Attributes. 56
The Panel Package. 56
4.9. File Descriptor Usage. 57
4
Using Windows
This chapter describes how to build SunView applications out of frames and
subwindows.
The first section presents the basic window routines. Succeeding sections give
examples, ranging from the simplest possible application to a moderately useful
file manager. For quick reference, the examples are given in the table below:
Table 4-1 Window Usage Examples
Example
Description
Illustrates
Page
hello j^or Id
Minimal SunView program.
Compilation, frames.
37
simple jpanel
Panel w/message and button.
Basic attributes, panels.
39
lister
Front end to Is
Panels, tty subwindows.
42
filer
File manager
Pop-ups, Selection Service.
44
image browserl
Displays images
Subwindow layout.
50
image _browser_2
Displays images
Row/column space.
53
Summary Listing and Tables To give you a feeling of what you can do with frames and subwindows, the fol¬
lowing page lists the available window and frame attributes, functions and mac¬
ros. Many attributes are discussed as they occur in the examples, and in other
chapters (use the Index to check). However, this chapter does not attempt com¬
plete coverage of all the attributes. All are briefly described with their arguments
in the window and frame summary tables in Chapter 19, SunView Interface Sum¬
mary:
□ the Window Attributes table begins on page 379;
□ the Frame Attributes table begins on page 382;
□ the Window Functions and Macros table begins on page 384;
□ the Command Line Frame Arguments table begins on page 386.
33
Revision A, of May 9, 1988
34 SunView 1 Programmer’s Guide
Window Attributes
WIN BELOW
WIN FIT WIDTH
WIN_PERCENT_WI DTH
WIN BOTTOM_MARGIN
WIN_FONT
WIN_P ICK__INPUT_MASK
WIN CLIENT DATA
WIN_GRAB_ALL_INPUT
WIN_PIXWIN
WIN COLUMNS
WIN_HEIGHT
WIN_RECT
WIN COLUMN GAP
WIN_HORIZONTAL_SCROLLBAR
WIN_RIGHT_MARGIN
WIN COLUMN_WIDTH
WI N_I GNORE_KBD_EVENT
WI N__R I GHT_OF
WIN CONSUME KBD EVENT
WIN_I GNORE_KBD_EVENT S
WIN_ROW_GAP
WIN CONSUME KBD EVENTS
WIN_I GNORE_PICK_EVENT
WIN_ROW_HEIGHT
WIN CONSUME PICK EVENT
WIN_IGNORE_PICK_EVENTS
WIN_ROWS
WIN CONSUME PICK EVENTS
WIN_INPUT_DESIGNEE
WIN_SCREEN_RECT
WIN CURSOR
WIN_KBD_FOCUS
WINJSHOW
WIN DEVICE_NAME
WI N__KBD_INPUT_MASK
WIN__TOP_MARGIN
WIN DEVICE NUMBER
WIN LEFT MARGIN
WINJTYPE
WIN ERROR MSG
WIN__MENU
WI N_VERT I CAL__S CROLLBAR
WIN_EVENT_PROC
WIN_MOUSE__XY
WIN_WIDTH
WIN_EVENT_STATE
WIN_NAME
WIN__X
WIN_FD
WIN_OWNER
WIN_Y
WIN FIT HEIGHT
WIN_PERCENT_HEIGHT
Frame Attributes
FRAME_ARGS
FRAME_DEFAULT_DONE_PROC
FRAME_NO_CONFIRM
FRAME_ARGC_PTR_ARGV
FRAME_DONE_PROC
FRAME_NTH_SUBFRAME
FRAME BACKGROUND_COLOR
FRAME_EMBOLDEN_LABEL
FRAME_NTH_SUBWINDOW
FRAME_CLOSED
FRAME_FOREGROUND_COLOR
FRAME_NTH_WINDOW
FRAME_CLOSED_RECT
FRAME_ICON
FRAME_OPEN_RECT
FRAME_CMDLINE_HELP_PROC
FRAME_INHERIT_COLORS
FRAME_SHOW_LABEL
FRAME_CURRENT_RECT
FRAME_LABEL
FRAME_SUBWINDOWS_ADJUSTABLE
Window Functions and Macros
window_bell(win)
window_
get(win, attribute)
window create(owner, type.
attributes)
window_
loop(subframe)
window default event_j?roc (window, event, arg)
window_
main_loop(base_frame)
window_destroy (win)
window_
read event(window, event)
window_done(win)
window_
_refuse_kbd__focus (window)
window__f it (win)
window_
release event lock(window)
window_fit_height(win)
window_
return(value)
window_fit_width(win)
window_
set(win, attributes)
Revision A, of May 9, 1988
Chapter 4 — Using Windows 35
4.1. Basic Routines
This section introduces the basic routines for using windows. It explains how to
create, modify, and destroy windows.
Creating a Window
You create all windows with the function:
Window
window_create(owner, type, attributes)
Window owner;
<windowtype> type;
<attribute-list> attributes;
If you recall from Chapter 2, The SuriView Model , a SunView application is
implemented as a hierarchy of frames. Each frame owns one or more subwin¬
dows. The frame at the top of the hierarchy (the base frame) will have a null
owner. In the above function, the owner parameter is the handle of the window
to which the window returned by window_c re ate () will belong. The type
parameter is the type of the new window; for example, FRAME, PANEL,
TEXTSW, CANVAS, Or TTY.
A very simple example of this function would be to create a panel belonging to a
frame called base_f rame, you would use:
Panel panel;
window_create(base_frame. Panel, 0);
Initiating Event Processing
The window_create () call does not display the frame on the screen. You
bring it to life after creating a base frame and its subwindows and subframes, by
calling window__main_loop (base_f rame) . This call displays the frame
on the screen and begins processing the events by passing control to the Notifier.
Chapter 2, The SunView Model, gave a brief explanation of the Notifier.
Keep in mind that subframes are treated different from base frames because they
are not tied to the base frame that is activated in the window_main_loop ()
call. In addition, if you create a subframe with WIN_SH0W set to TRUE, when
the user tries to manipulate the subframe ‘garbage’ data will appear on the
screen.
Modifying and Retrieving
Window Attributes
You modify and retrieve the value of window attributes with the following two
functions:
int
window set(window, attributes)
Window window;
<attribute-list> attributes;
caddr_t
window_get(window, attribute)
Window window;
Window attribute attribute;
®sun
\r microsystems
Revision A, of May 9,1988
36 SunView 1 Programmer’s Guide
NOTE If you call window_get () and specify an inappropriate attribute, a zero will
be returned. For example, a sub frame cannot be closed. Therefore, the call
window_get ( sub_f rame, FRAME_CLOSED_RECT ) will not work, so the
value returned will be zero. A segmentation violation will occur if an attempt is
made to dereference the return value.
When you get a pointer back from window_get (), the pointer points into a
private data structure, whose contents may change. 7
You destroy windows with the following two functions:
Destroying Windows
int
window_destroy(window)
Window window;
int
window_done(window)
Window window;
The difference between these two is that window_destroy () destroys only
window and its subwindows and subframes. window_done (), on the other
hand, destroys the entire hierarchy to which the subwindow or subframe belongs.
When window_destroy () is called on a window, the corresponding file
descriptors cannot be used again until the Notifier is called. The file descriptor
associated with the window is not reclaimed until the notifier has a chance to dis¬
tribute notifications again.
The way window_destroy () works is that it asks the window owner if it is
willing to be destroyed. If so, it queues up a notification procedure to destroy the
window. This delay protects the program from destroying a window that is being
accessed in the current call stack. You can work around this restriction, assum¬
ing you never reference this window again, by calling
notif y_f lush_pending () after calling window_destroy ().
7 For most attributes the pointer returned by window_get () points into per-window storage, but for some
the storage is static, per-process data. These attributes are flagged in the tables Chapter 19, SunView Interface
Summary.
Revision A, of May 9, 1988
Chapter 4 — Using Windows 37
4.2. Example 1—
hello_world
In learning a new programming language or environment, it usually helps to
begin with a small program that simply prints some output. By creating, compil¬
ing, loading, and running the program, you will master the mechanical details.
Here is a small SunView program:
r A
♦include <suntool/sunview.h>
main ()
{
Frame frame;
frame = window_create(NULL, FRAME,
FRAME LABEL, "hello world",
0);
window main loop(frame);
}
^_ j
After you create the above program in a file called hello world. c, you com¬
pile it with the command:
r \
% cc -o hello^world hello^wbrld.c -launtool ^-lsunwindow -lpixrect
Where,
□ hello_world is the executable output file that will be created
□ -lsuntool specifies to link with the suntool object library
□ -lsunwindow specifies to link with the sunwindow object library
□ -lpixrect specifies to link with pixrect object library
After you compile the program, type “hello_world”, and the window will come
up as shown in Figure 4-1 — a single frame with the words “hello world” in the
frame header:
microsystems
Revision A, of May 9,1988
38 SunView 1 Programmer’s Guide
hello
world
Figure 4-1 Hello World Window
This window is “alive” within the SunView user interface; it can be closed,
moved, resized, hidden, etc. When closed, a default icon is displayed, which
contains the text from the frame header.
Revision A, of May 9, 1988
Chapter 4 — Using Windows 39
4.3. Example 2— The next program is more complex than the first program. It creates a frame that
simple_panel contains a frame label and a panel that contains a panel button and a message.
This program also includes an image that appears when the window closes down
to an icon. Some basic attributes dealing with fonts, icons, help, error messages
and parsing command-line flags are introduced.
#include <stdio.h>
#include <suntool/sunview.h>
♦include <suntool/panel.h>
♦include <suntool/icon.h>
static void quit_proc();
Frame frame;
Panel panel;
Pixfont *bold;
Icon icon;
static short icon_ji.mage [ ] = {
♦include <images/hello_world.icon>
};
mpr_static(hello_world, 64, 64, 1, icon_image);
main(argc, argv)
int argc; char **argv;
{
bold = pf_open("/usr/lib/fonts/fixedwidthfonts/screen.b.12”);
if (bold — NULL) exit(l);
icon = icon_create(ICON_IMAGE, &hello_world, 0);
frame = window_create(NULL, FRAME,
FRAME_LABEL,
FRAME_ICON,
FRAME_ARGS,
WI N__ERROR_MS G,
0 );
”hello_world_panel",
icon,
argc, argv,
"Can't create window.".
panel ** window__create (frame, PANEL, WIN_FONT, bold, 0);
panel__create_item (panel, PANEL_MESSAGE,
PANEL_LABEL_STRING, "Push button to quit.", 0) ;
panel_create_item(panel, PANEL_BUTTON,
PANEL_LABEL_IMAGE, panel_button_image(panel, "Good-bye", 0, 0),
PANE L_N OTIFY_PROC, quit_proc,
0 );
window_fit(panel);
window_fit(frame);
window_main_loop(frame);
static void
quit _j?roc ()
{
window_set(frame, FRAME_NO_CONFIRM, TRUE, 0);
window_destroy(frame);
}
W sun
\r microsystems
Revision A, of May 9, 1988
40 SunView 1 Programmer’s Guide
This program creates a frame containing a single panel with a message and a but¬
ton:
Figure 4-2 Hello World Panel
Some Frame Attributes
FRAME LABEL
FRAME ICON
WIN ERROR MSG
The features and attributes used in the above program are discussed below.
The attributes are discussed below in the order that they appear in the above
panel.
The string given as the value for FRAME_LABEL will appear in a black frame
header strip at the top of the frame. If you do not want the label and the frame
header to appear, then set the attribute FRAME_SHOW_LABEL to FALSE.
The program used FRAME_iCON to specify the icon to be shown when the frame
is closed. This is done by first using the macro mpr_static () to define a
static memory pixrect that contains this data. Where hello_world is the
name of the pixrect to be defined. The next three arguments specify the width,
height, and depth of the image. Typically, for an icon, this is 64, 64, and 1. The
final argument is an array of shorts that contains the bit pattern of the icon image.
It takes its image from the file
/usr/include/images/hello_world. icon. This statically defined
image is passed to icon_create () at runtime.
The application uses FRAME ARGS 8 to pass command-line arguments given by
the user to the frame. A set of command line arguments are recognized by all
frames. These arguments allow the user to control such basic attributes as the
frame’s dimensions and label and whether the frame’s initial state is open or
closed, etc. These arguments begin with -W\ for a complete list of them see the
Command Line Frame Arguments table in Chapter 19, SunView Interface Sum¬
mary.
WlN_ERROR_MSG provides a simple form of error checking. If this attribute is
not specified, then window_create () will return 0 on failure. If a value for
WIN_ERROR_MSG is specified and window_create () fails, then it will print
the error message on stderr and exit with a status of 1.
8 As an alternative to FRAME ARGS, you can use FRAME_ARGC_PTR_ARGV, which takes a pointer to
argc, rather than argc itself. This attribute causes window_create () to strip all arguments beginning with
-W out of argv, and decrement argc accordingly.
Xr microsystems
Revision A, of May 9,1988
Chapter 4 — Using Windows 41
Panels
The panel is created by calling window_create () with the previously created
frame as the owner and PANEL as the window type.
Fonts
By default, text in the panel is rendered in the default system font, which
window_create () obtains by calling pf_default () . 9 The program
specified a font by first opening the font with pf_open (), and then passing it
into the panel as WIN_F0NT.
NOTE In the SunView context, note that setting WIN_FONT is not equivalent to specify¬
ing a font at run time with the -Wt command-line argument: -Wt opens the
default system font, win_font doesn’t. The only window types that currently
make use of WIN_F0NT to render characters are panels and text subwindows.
Panel Items
The panel contains two panel items: the message saying “Push button to quit.”
and the Good-bye button. They are created with panel_create_item ().
Notify Procedure
The concept of callback procedures was introduced in Chapter 2, The SunView
Model. Callback procedures for panel items are known as notify procedures.
The program registered its notify procedure quit_proc ( ) with the Quit but¬
ton using the attribute PANEL_NOTlFY_PROC. quit_proc ( ) is called when
the user selects the button. It in turn calls window_dest roy (), which, as
explained in the earlier subsection on Destroying Windows, causes
window_main_loop () to return. Before calling window destroy(),it
disables the standard SunView confirmation by setting the attribute
FRAME_N0_C0NFIRM for the frame.
Window Sizing —
window fit ()
The final feature illustrated by the example is the use of the window_f it ()
macro. This macro causes a window to exactly fit its contents.
The contents of a panel are its panel items; the contents of a frame are its subwin¬
dows. Therfore, the example program calls window_f it () twice, first fitting
the panel around its two items, then fitting the frame around its panel.
A window_f it_width () macro and a window_f it_height () macro
are used to permit adjusting in only one dimension. These correspond to the
window attributes WIN_FIT_WIDTH and WIN_FIT_HEIGHT.
Fitting Frames Around
Subwindows
*
Since Release 3.2, if you use window_f it () or its variants for sizing the
width and height of a frame, you need to be careful that the subwindows have
some specified size, or they will be shrunk very small by the window fit ()
call. Usually you give a subwindow a fixed size in one or both dimensions, or
size it to be a percentage of the frame’s size. The default size of a frame is that it
encloses an area 34 rows by 80 columns in its default font.
9 For details on fonts see the Pixrect Reference Manual.
©sun
\r microsystems
Revision A, of May 9, 1988
42 SunView 1 Programmer’s Guide
4.4. Example 3— lister Figure 4-3 illustrates a program to help manage files. The first version simply
lets the user list files in the current directory, forming a front-end to the ls(l)
command:
Figure 4-3 lister
The tool presents two subwindows. The top subwindow is a control panel with a
text item. It contains a place to specify the files to be listed, a List button, and a
Quit button.
Below the control panel is a tty subwindow. When the user pushes the List but¬
ton, the program constructs a command string consisting of the string “Is ”, fol¬
lowed by the value of the File: item, followed by a newline, and inputs the com¬
mand string to the tty subwindow by calling ttysw_input ().
The program is listed in its entirety below.
Notice that the frame, the panel and the tty subwindow are all declared as type
Window. They could just as well have been declared as type Frame, Panel
and Tty.
XT microsystems
Revision A, of May 9,1988
Chapter 4 — Using Windows 43
♦include <suntool/sunview.h>
♦include <suntool/panel.h>
♦include <suntool/tty.h>
Window frame, panel, tty;
Panel__item fname_item;
static void ls_proc(), quit_proc();
main (argc, argv)
int argc; char **argv;
{
frame = window_create(NULL, FRAME,
FRAME_ARGS, argc, argv,
FRAME_LABEL, "lister",
0 );
panel = window_create(frame, PANEL, 0);
create j?anel__items ();
tty = window_create(frame, TTY, 0);
window_main_loop(frame);
exit(0);
}
•
create_j>anel_items ()
{
fname_item = panel__create__item (panel, P ANEL__TEXT,
PANEL_LABEL_STRING, "File: ",
P ANEL_VALUE_D I SPLAY__LENGTH, 55,
0 );
panel_create__item(panel, PANEL_BUTTON,
PANEL_LABEL_IMAGE, panel_button_image(panel, "List", 5, 0),
PANEL_N OTIFY_PROC, ls_proc,
0 );
panel_create__item (panel, PANEL__BUTTON,
PANEL_LABEL__IMAGE, panel_button_image(panel, "Quit”, 5, 0),
PANEL_NOTIFY_PROC, quit_proc,
0 );
window_fit_height (panel) ;
}
static void
ls_j?roc (/* ARGS UNUSED */)
{ "
char cmdstring[256];
sprintf (cmdstring, "Is %s\n", panel__get_value (fname__itern) ) ;
ttysw__input (tty, cmdstring, strlen (cmdstring));
static void
quit_proc(/* ARGS UNUSED */)
{
window_destroy (frame) ;
}
v----->
Revision A, of May 9, 1988
44 SunView 1 Programmer’s Guide
4.5. Example 4 —filer Our next example builds on the simple front end to Is given in the previous
example to create a more interesting file manipulation tool. This application
illustrates the use of the text subwindow, the Selection Service, and pop-ups —
windows that appear on the screen and disappear dynamically during execution
of a program.
In appearance, filer is similar to lister, in that it contains a control panel and tty
subwindow. The user specifies the directory and file, and pushes the List button,
causing the Is command to be sent to the tty subwindow:
Figure 4-4 filer
f i ler
[List Pi rectory) [Set Is flags') [Edit] [Delete) [Quit)
Filing Mode: C Use "File:" item
Directory: /usr/vieu/doc/app/code
File: *.c
/usr/vi eui/doc/app/code/confi rm. c
/usr/view/doc/app/code/dctool.c
/usr/view/doc/app/code/filer.c
/usr/view/doc/app/code/font menu.c
/usr/view/doc/app/code/hello_worId.c
/usr/view/doc/app/code/image_browser_l.c
/usr/view/doc/app/code/image_brouser_2 .c
/usr/view/doc/app/code/1ister.c
/usr/view/doc/app/code/menugenproc.c
/usr/view/doc/app/code/resize_demo.c
/usr/view/doc/app/code/seln_demo,c
/usr/view/doc/app/code/showcolor .c
/usr/view/doc/app/code/simple_canvas.c
/usr/view/doc/app/code/simplempanel.c
/usr/view/doc/app/code/spheres.c
/usr/view/doc/app/code/tty_1o.c
/usr/view/doc/app/code/typein.c
polar% Q
There are three new buttons, each of which illustrates a typical use of pop-ups:
Set Is flags a pop-up property sheet for setting options to Is;
Edit a pop-up text subwindow for browsing and editing files;
Delete a pop-up confirmer which forces the user to confirm or cancel.
The three buttons are discussed in the pages that follow. The discussion makes
reference to specific routines in the filer program, which is listed in its entirety as
filer in Appendix A, Example Programs .
xr microsystems
Revision A, of May 9,1988
Chapter 4 — Using Windows 45
Pop-ups In SunView, pop-ups are implemented as subframes containing subwindows.
The subframe, along with its subwindows, is displayed and undisplayed as
needed. Pop-ups may be displayed in either a blocking or a non-blocking mode.
Examples of SunView pop-ups include the mailtool’s composition window and
textedit’s search and replace.
Pop-up Text Subwindow The Edit button illustrates a non-blocking pop-up. When the user selects a
filename and presses the button, a pop-up text subwindow containing the file
appears:
Figure 4-5 A Pop-up Text Subwindow
f 1 ler
[List Directory] [Set Is flags] [Edit] [Delete] [Quit]
Filing Mode: O Use "File:" item
D1rectory: /usr/view/doc/app/code
File: confirm.c
/usr/view/doc/app/code/confirm.c
/usr/view/doc/app/code/dctool.c
/usr
/usr
confirm.c ■
i——n—r— —. —— — — __
/usr
/usr
/usr
V
#ifndef lint
static char sccsid[] - "@(#)confirm.c 1.4 87/01/07 Copyr 1
/usr
986 Sun Micro";
/usr
#endif
/usr
y*********************************************************
/usr
/
/usr
/usr
#include <suntool/sunvieu.h>
/usr
#include <suntool/panel,h>
/usr
/usr
static Frame init_confirmer();
/usr
static int confirm();
pola
static void yes_no_ok();
▲
int
confirm_yes(message)
Both the subframe and text subwindow for the pop-up are created at initialization
time with the calls:
-—-
edit_frame = window_create(base_frame, FRAME,
FRAME_SHOW_LABEL, TRUE,
0 ) ;
editsw = window_create(edit_frame, TEXTSW, 0);
<--- j
When the user selects the Edit button, the notify procedure edit_proc () is
invoked. This function first calls the Selection Service to get the name of the file
the user has selected. 10
microsystems
Revision A, of May 9, 1988
46 SunView 1 Programmer’s Guide
It then loads the file into the text subwindow, sets the frame header to the
filename, and displays the frame with these two calls:
window_set(editsw f TEXTSW_FILE, filename, 0);
window set(edit_frame, FRAME_LABEL, filename, WIN_SHOW, TRUE, 0);
Pop-up Property Sheet The property sheet shown in Figure 4-6 is a typical example of a non-blocking
pop-up. By pushing the Set Is flags button, the user can get a property sheet
which allows him to set some of the options to the Is command. While the pro¬
perty sheet is displayed, the user can continue to interact with the application,
setting options now and then. The user can cause the pop-up to disappear at any
time by pushing the Done button, selecting Done from the subframe’s menu, or
by pressing the SunView function key labelled 1 Open ] .
Figure 4-6 A Non-blocking Pop-up
f i ler
Invoking the ‘Props’ Menu Item Two attributes are used to control whether the ‘Props’ menu item is active or able
to be invoked in the frame’s menu. The code fragment given below is taken
from the filer program.
The FRAME PROP S_ACT ION_PROC attribute specifies which procedure will
be called when the ‘Props’ menu item is chosen or the [ Props J key is pressed. In
the code below, FRAME_PROPS_PROC specifies that the procedure
ls_f lags_proc () is called when the I Props I key is pressed.
microsystems
Revision A, of May 9,1988
Chapter 4 — Using Windows 47
WIN SHOW
Pop-up Confirmer
The FRAME_PROPS_ACTlVE attribute specifies whether the procedure that is
specified by the FRAME_PROPS_ACTlON_PROC will be called or not If the
attribute FRAME_PR0PS_ACTIVE is TRUE, then the frame menu will contain
an un-greyed ‘Props’ menu item. If the attribute FRAME_PROPS_ACTlVE is
FALSE, then the frame menu will contain a greyed out ‘Props’ menu item.
/—
>
base_frame = window_create(NULL, FRAME,
FRAME_ARGS,
argc, argv.
F RAME_L ABE L ,
"filer”.
F RAME_P ROP S_AC TI ON_P ROC ,
ls__f lags_proc.
FRAME PROPS ACTIVE,
TRUE,
0);
s_
-j
The display of a non-blocking pop-up is controlled using the WIN_SH0W attri¬
bute. The initialization routine create_ls_flags_popup() creates the
subframe, panel, and panel items for the property sheet. When the subframe is
created, WIN_SHOW is FALSE. 11 The notify procedure for the Set Is flags but¬
ton, ls_f lags_proc (), simply sets WIN_SH0W to TRUE for the subframe. 12
When the notify procedure for the List button, ls_proc (), is called, it calls
compose_ls_options () to construct the appropriate string of flags based
on the settings of the items in the property sheet.
Both the property sheet and the editing subwindow described in the preceding
section are examples of non-blocking pop-ups, in which the application contin¬
ues to receive input while the pop-up is displayed.
Blocking pop-ups differ in that, when displayed, they receive all input directed to
the screen. Blocking pop-ups are appropriate when you want to force the user to
confirm or cancel an irreversible operation before changing the application’s
state in any way.
Most uses of blocking pop-ups should use the alert package described in Chapter
10, Alerts. In the example given below, filer uses an alert for the Delete button
confirmation. However, if you want to use other panel features, or other kinds of
windows, then you can use window_loop () for the same effect.
For example, in Figure @NumberOf(alert-win), when the user makes a selection
and pushes the Quit button, filer displays a pop-up asking for confirmation. All
input is directed into this confirmer, and the user is forced to either accept the
deletion by selecting Yes or cancel it by selecting No :
11 Note that while WIN_SHOW defaults to TRUE for base frames, it defaults to FALSE for subframes. The
same holds for FRAME_SHOW_LABEL.
12 Note that the subframe won’t actually be displayed until control is returned to the Notifier.
Revision A, of May 9, 1988
48 SunView 1 Programmer’s Guide
Figure 4-7 Pop-up Confirmer
List Directory] [Set Is flags) [Edit] [Delete] ||
Filing Mode: 6 Use "File:" item
jiii
Directory:
File:
/usr/view/1.75/usr/src/usr.bin/sunwindows/suntoo1/examples
B
apia% Is
Makefile
Makefile.customer
Makefile.doc
jiiil Makefile, old
SCCSG
addnewtest* |
addnewtest.c
animatecolor*
animatecolor.
bounce*
bounce.c
canvas_input*
|: canvas.input. c
| canvas_repaint*
| canvas.repaint.c
coloredit*
coloredit.c
confirm.c
apia% []
detool*
dctool.c
err
filer*
filpr
menugenproc.c
resize.demo*
resize.demo.c
seln_demo*
"ipln rlpmn r .
Are you sure you want to Quit?
Confirml
[Cane
icelj
image _br ows e r _2 *
image _browser_2. c
loopback*
loopback.c
menugenproc*
tty.io.c
typein*
typein.c
window_loop The display of a non-blocking pop-up is controlled using the WIN_SH0W attri¬
bute. The display of a blocking pop-up, on the other hand, is controlled with the
two functions window_loop () and window_return ().
caddr_t
window_loop(subframe)
Frame subframe;
void
window_return(return_value)
caddr_t return_value;
window_loop () causes the pop-up to be displayed and receive all input
directed to the screen. The call will not return until window_return () is
called from one of the pop-up’s notify procedures. The value passed to
window_return () as return_value will be returned by
window_loop (). Its interpretation is up to the application. That is, it may be
used to indicate whether the command was confirmed, whether a valid file name
was entered, and so on.
Xr ’microsystems
Revision A, of May 9,1988
Chapter 4 — Using Windows 49
Restrictions on Pop-Up Frames
There are some restrictions on pop-up frames displayed using
window_loop():
□ You can only have one subwindow in the pop-up frame.
o The only subwindow types that work properly are canvases and panels.
These limitations do not apply to non-blocking pop-ups displayed using
WIN_SHOW.
Controlling a Pop-up or
Frame’s Shadowing
Sun’s convention is that only transient items such as pop-ups have shadows.
However, using the attribute FRAME_S HOW_S H ADOW you may control the sha¬
dowing effect of a frame or a subframe:
□ If you want your base frame to have a shadow, then set the attribute
FRAME_SHOW_SHADOW to TRUE.
□ You may stop a shadow from appearing with a sub_frame during create time
by setting FRAME_SHADOW to FALSE.
Xr microsystems
Revision A, of May 9, 1988
50 SunView 1 Programmer’s Guide
4.6. Example 5— Figure 4-8 illustrates how to specify the size and position of subwindows in order
image_browser_1 to get the layout that you want This application lets the user view the images in
files generated by iconedit. The user first presses the List button to get a list¬
ing. The user then selects a file that contains an image and press the Show but¬
ton to view the image:
Figure 4-8 imagebrowser_1
This example presents a somewhat more complex subwindow layout: the tty
subwindow has been moved to the left, the control panel to the upper right, and a
panel for displaying the image added on the lower right
Specifying Subwindow Size You can specify the size of a subwindow either in pixels, with WIN_HEIGHT
and WIN_WIDTH or in terms of rows and columns, with WIN_R0WS and
WlN_COLUMNS. 13 If its dimensions are not specified, then a subwindow will
extend in the y direction to the bottom edge, and in the x direction to the right
edge of the frame. In this case the subwindow’s height and width will have the
special value WlN_EXTEND_TO_EDGE, 14 and will track the edge of the frame
at run time, expanding or shrinking appropriately when the user resizes the
frame.
Keep in mind that if you alter the size of a frame so that it exactly borders on a
subwindow by calling window_f it (), the dimension of the subwindow that
touches the frame will automatically become WIN_EXTEND_TO_EDGE.
13 Row/column space is discussed in the next example.
14 It is meaningless to set the width or height of a frame to WIN EXTEND TO EDGE, and it will interfere
with subwindow behavior.
microsystems
Revision A, of May 9, 1988
Chapter 4 — Using Windows 51
Default Subwindow Layout The default subwindow layout algorithm is simple. The first subwindow is
placed at the upper left comer of the frame (leaving space for the frame’s header
and a border). If the width of the previously-created subwindow is fixed, not
extend-to-edge, then the next subwindow is placed to the right of it. If the width
of the previously-created subwindow is extend-to-edge, then the next subwindow
is placed below it, at the left of the frame.
Explicit Subwindow Layout This default layout algorithm handles only veiy simple topologies. Sun View
provides attributes that allow you to specify more complex layouts by explicitly
positioning subwindows. You can position one subwindow relative to another by
using WIN_BEL0W and win_RIGHT_OF. These attributes take as their value
the handle of the subwindow you want the new subwindow to be below or to the
right of.
image_browser_l , pictured on the preceding page, illustrates the use of
window_f it ( ) along with explicit subwindow positioning to obtain a particu¬
lar layout. The relevant calls are shown below:
' ->
tty = window_create(frame, TTY,
WIN_ROWS, 20,
WIN_COLUMNS, 30,
0 );
control_panel = window_create(frame, PANEL, 0);
(create panel items...)
window_fit (control_j?anel) ;
display_panel = window_create(frame, PANEL,
WIN_BELOW, control__panel,
WIN_RIGHT_OF, tty,
0 );
window_fit (frame) ;
<_____y
First the tty subwindow is created with a fixed height and width. Then the con¬
trol panel is created, with no specification of origin or dimensions.
Since the width of the previous subwindow was fixed, the control panel is placed
by default just to the right. After its items are created, the control panel is shrunk
around its items in both dimensions with window_f it ().
Next, the display panel is created and explicitly positioned below the control
panel and to the right of the tty subwindow. Both dimensions of the display
panel default to win_extend_to_edge.
Finally, window_f it () is called to shrink the frame to the height of the tty
window and the combined width of the tty window and the control panel. 15
15 window_fit () causes the window to shrink until it encounters the first fixed border. Subwindows
which are extend-to-edge don’t stop the shrinking.
microsystems
Revision A, of May 9, 1988
52 SunView 1 Programmer’s Guide
NOTE One thing to watch out for is that WIN_BEL0W only affects the subwindow’s y
dimension, and WIN_RIGHT_OF only effects the x dimension.
You can also specify the origin of a subwindow in pixels using WIN_X and
WIN_Y. The computations for these attributes take the borders and header of the
frame into account, so that specifying WIN_X and WIN_Y of 0 will then result in
the subwindow being placed correctly at the upper left comer of the frame.
The program resize demo, listed in Appendix A, uses these attributes to lay out
its subwindows in a non-standard manner.
If you programmatically change the size or position of subwindows after you
create them, then you must explicitly re-specify the origin of any subwindows
that are below or to the right of the altered subwindows. This must be done even
if you specified the positions of these other subwindows using relative position
attributes, such as win_below.
This step is necessary because subwindows are not automatically laid out again
when the positions and sizes of other subwindows are changed. They are only
laid out again if the frame changes size. When re-specifying the layout of the
other subwindows, you can use relative position attributes such as WlN_BELOW.
The Rect Structure The attributes WIN_X, WIN_Y, WIN_WIDTH and WIN_HEIGHT, taken together,
define the rectangle occupied by a window. This rectangle is actually stored as a
Rect struct, which you can get or set using the attribute WIN_RECT. The
definition of a Rect, found in <sunwindow/rect. h>, is: 16
typedef struct rect {
short r_left;
short r_top;
short r_width;
short r_height;
} Rect;
The Rect is the basic data structure used in SunView window geometry. Where
complex shapes are required, they are built up out of groups of rectangles. 17
Changing Subwindow Layout
Dynamically
Specifying Subwindow Sizes
and Positions
16 The result that a window returns is relative to a frame’s positioning space. It is not self-relative and it is
not parent-relative. Therefore, WIN RECT should only be used for window positioning operations. Do not use
itforpw_lock ().
17 For a detailed discussion of rectangle geometry, including useful macros for operating on rectangles, see
the chapter entitled Reds and Rectlists in the SunView 1 System Programmer s Guide.
Revision A, of May 9, 1988
Chapter 4 — Using Windows 53
4.7. Example 6—
image browser_2
In the next example, when the user specifies a filename and pushes Browse the
images in the files are displayed in a scrollable panel:
Figure 4-9 imagebrowser_2
The point of this example is to illustrate how you can use row!column space to
specify the size of a subwindow. The goal was to make the panel just the right
size to display a single page of icons, with four rows, four columns, and 10 pixels
of white space around each icon.
Row/Column Space Row/column space refers to a logical grid defining the rows and columns of a
window. You can define the row/column space for a window by using the attri¬
butes in the following table:
Table 4-2 Window Row!Column Geometry Attributes
Attribute
Description
Default
Def. in Panels
WIN_BOTTOM_MARGIN
Bottom margin.
0
(same)
WIN_COLUMN_GAP
Space after columns.
0
(same)
WIN_COLUMN_WIDTH
Width of a column.
Width of WINJFONT.
(same)
WIN_LEFT_MARGIN
Left margin.
5
4
WIN_RIGHT_MARGIN
Right margin.
5
0
WIN_ROW_GAP
Space after rows.
0
5
WIN_ROW_HEIGHT
Height of a row.
Height of WIN FONT
(same)
WIN_TOP_MARGIN
Top margin.
5«
4
19 In frames with headers, the default for WIN TOP MARGIN depends on the system font With the default
microsystems
Revision A, of May 9,1988
54 SunView 1 Programmer’s Guide
Defining a Panel’s Row/Column Using the row/column space attributes, the icon browsing panel pictured on the
Space preceding page is specified as follows:
r
>
Scrollbar scrollbar = scrollbar__c reate (SCROLL_MARGIN, 10 f 0) ;
bar_width = (int)scrollbar_get(scrollbar, SCROLL_THICKNESS,
0);
display_panel = window_create(base_
frame, PANEL,
WIN VERTICAL_SCROLLBAR, scrollbar.
WI N__ROW_HE IGHT,
64,
WIN_COLUMN_WIDTH,
64,
WIN_ROW_GAP,
10,
WIN_COLUMN_GAP,
10,
WIN_LEFT_MARGIN,
bar_width + 10,
WIN_TOP_MARGIN,
10,
WIN_ROWS,
4,
WIN COLUMNS,
4,
0);
window_set (display_j?anel, WIN_LEFT_
MARGIN, 10, 0);
V.
__ -J
This achieves our goal of a panel the right size for a 4x4 array of 64 pixel square
icons, with 10 pixels of white space around each icoa
Positioning Panel Items in Once you have defined your row/column space, you can position panel items
Row/Column Space within that space with the ATTR_ROW () and ATTR__COL () macros. 20 The code
fragment shown below shows how the items for the browsing panel are created
and positioned at the proper row and column each time the Browse button is
pushed:
f
\
for (row
= 0, image count * 0; image_count < files_count; row++)
for
(col = 0; col <= 4 && image_count
< files count; col++) {
if
(image = get_image(image_count))
{
panel_create_item(display_panel,
PANEL_MESSAGE,
PANEL__ITEM_Y,
ATTR_ROW(row),
PANE L__I TEM_X,
ATTR_COL(col) ,
PANEL_LABEL_IMAGE, image, 0);
}
image_count++;
}
-J
This example is complicated somewhat by an inconsistency in the way margins
are handled in the current release of SunView. The left and top margins are used
in two ways: for determining the size of the panel, and for determining the loca¬
tion of panel items positioned with ATTR_COL () and ATTR_ROW (). The size
computation does not take into account any scrollbar which may be present; the
positioning computation, on the other hand, does take the scrollbar into account
That is why, in the call to window_create () above, WIN_LEFT_MARGIN is
set to the width of the scrollbar plus 10 pixels, and then set immediately after¬
ward to 10 pixels.
system font, it defaults to 17.
20 These “character unit macros** are described fully in Chapter 18, Attribute Utilities.
Revision A, of May 9,1988
Chapter 4 — Using Windows 55
4.8. Attribute Ordering
Command-line Arguments
The general rule is that attributes in SunView are evaluated in the order they are
given. The following two examples of text subwindow calls illustrate how giv¬
ing the same attributes in different orders can produce different effects:
window_set(textsw, TEXTSW_FILE, "file_l", 0);
window_set(textsw, TEXTSW_FIRST, 20, TEXTSW_FILE, "file_2", 0) ;
window_set(textsw, TEXTSW_FILE, "file_l", 0);
window_set(textsw, TEXTSW_FILE, "file_2", TEXTSW_FIRST, 20, 0) ;
In the first pair of calls, the index is first set to the 20th character of f ile_l,
then f ile_2 is loaded, starting at character zero. The second pair of calls first
loads file 2, then sets the index in file 2 to 20.
The attribute FRAME_ARGS bears special mention. As described in the second
example in this chapter, simple_panel, this attribute causes the frame to process
the command-line arguments given by the user at run time. Some of these argu¬
ments correspond to attributes that can be set programmatically; for example, -
wh corresponds to win_rows. 21
The basic rule, that attributes are evaluated in the order given, applies equally to
attributes that are explicitly specified in the program and to those that are
specified at run time using their command-line equivalents. If a given attribute is
specified more than once, then the last setting is the one that takes effect. You
can therefore control whether your application or the user has the last word by
specifying attributes after or before FRAME_ARGS.
Let’s take a couple of examples:
window_create(0, FRAME,
FRAME_ARGS, argc, argv,
FRAME_LABEL, "LABEL FROM PROGRAM",
WIN_ROWS, 10,
0 );
window_create(0, FRAME,
FRAME_LABEL,
WIN_ROWS,
FRAME_ARGS,
0 );
"LABEL FROM PROGRAM",
10 ,
argc, argv.
Assume that the program was invoked with a command line containing the fol¬
lowing arguments:
-Wl "LABEL FROM COMMAND-LINE" -Wh 4
In the first call, by putting FRAME_ARGS at the start of the list, the application
overrides the command-line arguments, and guarantees that the frame header will
read “LABEL FROM PROGRAM” and the height will be 10 lines.
21 For a complete list of these arguments see the Command Line Frame Arguments table in Chapter 19,
SunView Interface Summary.
Revision A, of May 9, 1988
56 SunView 1 Programmer’s Guide
Different Classes of Attributes
The Panel Package
In the second call, since frame_args appears at the end of the list, the
command-line arguments override what the application has specified, resulting in
a label of “LABEL FROM COMMAND-LINE” and a height of 4 lines.
Keep in mind that if you specify WIN_F0NT, it does not override the font that
the user specified using -Wt.
In the case of different objects, the window attributes (those beginning with
WIN_) are processed after the others (FRAME_*, PANEL_*, and so on).
Suppose that you want to create a canvas with a scrollbar. You also want the
logical canvas to expand when the user makes the window bigger, but never to
shrink past its initial size, even if the user shrinks the window. The initial size of
the canvas should be the size of the “inner” portion of the window — not includ¬
ing the scrollbar.
The straightforward approach would be to simply set all relevant attributes when
the window is created, as in:
canvas
= window_create(frame, CANVAS,
WIN_VERTICAL_SCROLLBAR,
scrollbar_
\
create(0) ,
V
CANVAS AUTO SHRINK,
0);
FALSE,
This call, however, results in a canvas which is too big, extending underneath the
vertical scrollbar. This is because of the order in which the CANVAS_ and WIN_
attributes are evaluated.
Since the window attributes are evaluated after the canvas attributes, the canvas
size is set according to the initial size of the window, which does not have a
scrollbar. By the time WIN_VERTICAL_SCROLLBAR is evaluated, the canvas
refuses to shrink to the smaller inner portion of the window, since
CANVAS_AUTO_SHRINK has already been evaluated and set to FALSE.
In general, you can force a particular order of evaluation by using separate
window_set () calls, as in:
- >
canvas *= window_create(frame, CANVAS,
WIN_VERTICAL_SCROLLBAR, scrollbar_create(0),
0 );
window set(canvas, CANVAS_AOTO_SHRINK, FALSE, 0);
The panel package deviates from the norm in that its attributes are generally not
order-dependent. For example, you can specify the label of an item before the
font, and the font will be used even though it appears after the label.
The only thing to watch out for is that you can’t change the font in a single call,
as in:
»sun
XT microsystems
Revision A, of May 9,1988
Chapter 4 — Using Windows 57
/—
\
panel_set (text_item.
PANEL_FONT,
font_l.
PANEL_LABEL_STRING,
"Label:",
PANELJFONT,
font_2.
PANEL VALUE,
"initial value".
0);
V.
j
The above call will cause both the label and the value for text_item to be ren¬
dered in font 2.
4.9. File Descriptor Usage In SunView, each window is actually a device, /dev/win nnn, that is accessed
through a file descriptor. Other packages such as the selection service also use
file descriptors. In SunOS there is a limit to the number of file descriptors one
program can have open; in Release 4.0 it is 64. Thus it is possible for your appli¬
cation to run out of file descriptors.
The following table summarizes how file descriptors are used in SunView.
Table 4-3 SunView File Descriptor Usage
Window Type /
Package
FD Usage
How FDs are used
FRAME
1
1 for the window.
CANVAS
1
1 for the window.
TEXTSW
3
1 for the window,
+ 1 for the file to be edited (if any),
+ 1 for scratch (the /tmp/Text... file).
(2)
2 temporarily created during a save.
PANEL
1
1 for the window.
TTYSW
2
1 for the window,
+ 1 for the pty (pseudo-tty).
MENU
0
Fullscreen access uses the window’s FD.
ALERT
1
1 for positioning
Alerts have a frame and a panel;
however, the FDs are allocated for the
first alert and reused by subsequent alerts.
Pointer
0
Most pointers are managed by the kernel.
Icon
0
Frame uses same FD whether open or iconic.
Revision A, of May 9, 1988
58 SunView 1 Programmer’s Guide
Table 4-3 SunView File Descriptor Usage — Continued
Window Type!
Package
FD Usage
How FDs are used
Scrollbar
0
(implemented as a region — read the
SunView System Programmer’s Guide )
window manager
(1)
1 temporarily used for window
management operations.
UNIX
3
stdin/stdout/stderr
4
framebuffer
1
frame buffer FD gets allocated
automatically with the base frame. The screen
device must be opened for your program
to draw on it.
Selection Service
3
selection service fd’s
are allocated whenever there is something
that will set or get from the selection
service. For example, if you put in
selection service code or the first time
a panel item is allocated.
(1)
This uses sockets to communicate:
1 for the connection to the service
+ 1 to receive UDP requests
+ 1 TCP rendezvous socket for transfers.
1 transiently opened when a transfer
is in progress to carry it.
XT microsystems
Revision A, of May 9, 1988
Canvases
Canvases. 61
5.1. Creating and Drawing into a Canvas. 63
5.2. Scrolling Canvases. 64
5.3. Canvas Model. 65
The Canvas. 65
5.4. Repainting. 66
Retained Canvases. 66
Non-Retained Canvases. 66
The Repaint Procedure. 66
Retained vs. Non-Retained. 67
5.5. Tracking Changes in the Canvas Size . 67
Initializing a Canvas . 67
5.6. Automatic Sizing of the Canvas . 69
5.7. Handling Input in Canvases. 70
Default Input Mask. 70
Writing Your Own Event Procedure. 70
Translating Events from Canvas to Window Space. 70
Border Highlighting. 71
5.8. Color in Canvases. 72
Setting the Colormap Segment. 72
Color in Retained Canvases. 72
Color in Scrollable Canvases. 72
Canvases
The most basic type of subwindow provided by SunView is the Canvas. A can¬
vas is essentially a window into which you can draw.
For a demonstration of the various canvas attributes, run the program
/usr/demo/canvas_demo. For examples of canvases that illustrate event
handling, run the image editor iconedit(l). iconedit uses two canvases,
the large drawing canvas on the left, and the small proof area on the lower right.
In order to use canvases you must include the header file
<suntool/canvas.h>.
To give you a feeling for what you can do with canvases, the following page lists
the available canvas attributes, functions and macros. Many of these are dis¬
cussed in the rest of this chapter and elsewhere (use the Index to check). All are
briefly described with their arguments in the canvas summary tables in Chapter
19, SunView Interface Summary :
□ the Canvas Attributes table begins on page 319;
□ the Canvas Functions and Macros table begins on page 320.
microsystems
61
Revision A, of May 9, 1988
62 SunView 1 Programmer’s Guide
Canvas Attributes
CANVAS_AUTO_CLEAR
CANVAS_AUTO_EXPAND
CANVAS_AUTO_SHRINK
CANVAS_FAST_MONO
CANVAS_FIXED_IMAGE
CANVAS_HEIGHT
CANVAS_MARGIN
CANVAS__P IXWIN
C ANVA S_REP AI NT_PROC
CANVA S_RE SI ZE_PROC
CANVAS_RETAINED
CANVAS_WIDTH
Canvas Functions and Macros
canvas_event(canvas, event)
canvas_
_window_event(canvas, event)
canvas pixwin(canvas)
microsystems
Revision A, of May 9, 1988
Chapter 5 — Canvases 63
5.1. Creating and Drawing Like all windows in SunView, canvas subwindows are created with
into a Canvas window_create (). When drawing into a canvas use the canvaspixwin,
which you can get with the canvas_pixwin () macro.
The pixwin is the structure through which you render images in a window. You
draw points, lines and text on a pixwin with a set of functions of the form
pw _*Jl ) — pw_write (), pw_vector (), pw_text () etc. 22
Example 1:
As a beginning example, the following program puts up a canvas containing a
box with the words “Hello World!”:
♦include <suntool/sunview.h>
♦include <suntool/canvas.h>
main(argc, argv)
int argc;
char **argv;
{
Frame frame;
Canvas canvas;
Pixwin *pw;
/* create frame and canvas */
frame = window__create (NULL f FRAME, 0) ;
canvas = windowhereate(frame, CANVAS, 0);
/* get the canvas pixwin to draw into */
pw = canvas_pixwin(canvas);
/* draw top, bottom, left, right borders of box */
pw_vector(pw.
100,
100,
200,
100,
PIX_
SRC,
»—i
pw_vector(pw.
100,
200,
200,
200,
PIX~
[SRC,
l);
pw__vector (pw.
100,
100,
100,
200,
PIX_
SRC,
l);
pw_vector(pw.
200,
100,
200,
200,
PIX_
SRC,
l);
/* write text at (125,150) in default font */
pw_text(pw, 125, 150, PIX_SRC, 0, "Hello World!");
window_main_loop(frame);
exit(0);
The PIX_SRC argument to pw_vector () and pw_text () is a rasterop
function specifying the operation which is to produce the destination pixel
values. There are several other rasterop functions besides P IX_SRC; they are
described in Chapter 2 of the Pixrect Reference Manual. »
22 Pixwins and their associated functions are covered in detail in Chapter 7, Imaging Facilities: Pixwins.
Revision A, of May 9,1988
64 SunView 1 Programmer’s Guide
5.2. Scrolling Canvases
Example 2:
Many applications need to view and manipulate a large object through a smaller
viewing window. To facilitate this SunView provides scrollbars, which can be
attached to subwindows of type canvas, text or panel.
The code below creates a canvas that is scrollable in both directions:
frame = window_create(NULL, FRAME, 0)
canvas = window_create(frame, CANVAS,
CANVA S__AUT 0_SHR INK,
CANVAS_WIDTH,
CANVAS__HE IGHT,
WIN_VERTICAL_SCROLLBAR,
WIN_HORIZONTAL_SCROLLBAR,
0 );
FALSE,
1000 ,
1000 ,
scrollbar_create(0),
scrollbar create(0),
The distinction between the dimensions of the canvas and of the window is
important In the above example, we set the canvas width and height to 1000
pixels. Since the dimensions of the canvas subwindow (i.e. WIN_WIDTH and
WIN_HEIGHT) were not explicitly set, the subwindow extends to fill the frame.
The frame’s dimensions, in turn, were not explicitly set, so it defaults to 25 lines
by 80 characters in the default font The result is a logical canvas roughly the
area of the screen, which is viewed through a window about one fourth that size.
NOTE It is necessary to explicitly disable the ‘‘auto-shrink” feature in the above exam¬
ple. If this were not done, the canvas size would be truncated to the size of the
window. See Section 5.6, Automatic Sizing of the Canvas.
V microsystems
Revision A, of May 9, 1988
Chapter 5 — Canvases 65
5.3. Canvas Model The components of a canvas subwindow and their relationships can be seen in
Figure 5-1.
Figure 5-1 Canvas Geometry
Scrollbars
WINDOW HEIGHT
CANVAS WDTH
(CAN VAS_WI DTH -1.
CANVAS_HEIGHT-1)
The Canvas Think of the canvas itself as a logical surface on which you can draw. The width
and height of the canvas are set via the attributes CANVAS_WIDTH and
CANVAS_HEIGHT. So the coordinate system is as shown in Figure 5-1, with the
origin at the upper left comer and the point (CANVAS_WIDTH-1,
CANVAS_HEIGHT-1) at the lower right comer. Note that the logical canvas
origin is always at (0,0).
The Canvas Pixwin As mentioned above, you draw on the canvas by writing into the canvas pixwin,
which is retrieved via the CANVAS_PIXWIN attribute or the
canvas_pixwin () macro.
The canvas pixwin is set up to take scrolling into account by performing the
transformation from your canvas coordinate system to its pixwin coordinate sys¬
tem. So when you draw into the canvas pixwin using the pw_* functions you
don’t have to do any mapping yourself — the arguments you give should be in
the canvas coordinate system.
Between the frame border and the canvas pixwin is a margin, set via the attribute
CANVAS_MARGIN. This margin defaults to zero pixels, so in the simple case,
the canvas pixwin occupies the entire inner area of the window pixwin. If one or
more scrollbars are present, the canvas margin begins at the inside border of the
scrollbar.
Note the distinction between the pixwin of the canvas (attribute
CANVAS_P IXWIN) and the pixwin of the window (attribute WIN_PIXWIN).
The canvas pixwin is one of several regions of the window’s pixwin, which also
includes the regions occupied by the scrollbars and the margin.
Revision A, of May 9, 1988
66 SunView 1 Programmer’s Guide
5.4. Repainting
Retained Canvases
Non-Retained Canvases
The Repaint Procedure
The canvas package manages the canvas pixwin for you. In particular, the clip¬
ping list is restricted to the area of the canvas pixwin actually backed by the can¬
vas. This means that you can never draw off die edge of the canvas. For exam¬
ple, if you have set the canvas height to be less than the height of the canvas
pixwin, any pw_* operations that attempt to draw below the canvas height will
be clipped away.
By default, canvases are retained — i.e. the canvas package maintains a copy of
the bits on the screen in a backing pixrect, from which it automatically repaints
the screen image when necessary. If you wish to handle repainting yourself, you
can defeat this feature.
The canvas package allocates a backing pixrect the size of the logical canvas.
When the canvas width or height changes, a new backing pixrect of the proper
dimensions is allocated, the contents of the old pixrect are copied into the new
pixrect, and the old pixrect is freed.
For a non-retained canvas, set CANVAS_RETAINED to FALSE, and give your
own repaint function as the value of CANVAS_REPAlNT_PROC.
The repaint procedure is called whenever some part of the canvas has to be
repainted onto the canvas pixwia Note that if you supply a repaint proc, it will
be called even if the canvas is retained — i.e. the canvas package will not
automatically copy from the backing pixrect to the canvas pixwin.
The form of the repaint procedure is:
sample_repaint_proc(canvas, pixwin, repaint_area)
Canvas canvas;
Pixwin *pixwin;
Rectlist *repaint_area;
The first two arguments are the canvas and its pixwin (i.e. the value of
canvas_pixwin (canvas)). The third argument, repaint_area, is a
pointer to a list of rectangles (type Rectlist *) which define the area to be
painted. 23
Before the canvas package calls your repaint procedure, it restricts the clipping
list to the area which needs to be painted. Thus if your application is not capable
of repainting arbitrary areas of the canvas you can repaint the entire image
without worrying about excessive repainting.
If you choose not to redraw each individual rect in the repaint area, you can use
the rectangle given by repaint_area->rl_bound, which is the bounding
rectangle for the repaint area.
Note that if the attribute CANVAS_AUTO_CLEAR is TRUE, the canvas package
will clear the repaint area before calling your repaint procedure.
23 Rectlists are covered in detail in the chapter on Reds and Redlists in the SunView 1 System
Programmer’s Guide.
microsystems
Revision A, of May 9,1988
Chapter 5 — Canvases 67
A retained canvas has two advantages. First, the repainting will be faster since it
is a simple block copy operation. Second, it eliminates the need for the applica¬
tion to keep a display list from which to regenerate the image.
On the other hand there is a performance penalty on writing, since each operation
is performed both on the canvas pixwin and the backing pixrect. This penalty
may be reduced by using the pw_bat ch () call described in the chapter entitled
Imaging Facilities: Pixwins.
The client’s resize procedure is called whenever the canvas width or height
changes. Its form is:
sample_resize_proc(canvas, width, height)
Canvas canvas;
int width;
int height;
NOTE You should never repaint the image in the resize procedure, since if there is any
new area to be painted, the repaint procedure will be called later.
There are some subtle points to be aware of related to whether or not the image is
fixed size (CANVAS_FIXED_IMAGE is TRUE). In the default case the image is
fixed size, and the repaint procedure will not be called when the canvas gets
smaller, since there will be no new canvas area to be repainted. If the image is
not fixed size, then whenever the canvas size changes, the canvas package
assumes that the entire canvas needs to be repainted, and the repaint area will
contain the entire canvas.
Initializing a Canvas Neither the repaint procedure nor the resize procedure will be called until the
canvas subwindow has been displayed at least once. This allows you to create
and initialize a canvas without having to deal with the resize/repaint procedures.
The very first time the canvas is displayed, the resize procedure will be called
with the current canvas size. This initial call to the resize procedure allows you
to synchronize with the canvas size.
Retained vs. Non-Retained
5.5. Tracking Changes in
the Canvas Size
Revision A, of May 9, 1988
68 SunView 1 Programmer’s Guide
Example 3:
The canvas in the program below has a repaint procedure which fills the canvas
with an appropriately sized rectangle and diagonals.
♦include <suntool/sunview.h>
♦include <suntool/canvas,h>
static void repaint_canvas();
main(argc, argv)
int argc;
char **argv;
{
Frame frame;
frame = window_create(NULL, FRAME, 0);
window_create(frame, CANVAS,
CANVAS__RET AI NED, FALSE,
CANVAS_FIXED_IMAGE, FALSE,
CANVAS_REP AI NT_PROC, repa int_canva s,
0 );
window_main_loop (frame);
exit(0);
static void
repaint_canvas(canvas, pw, repaint_area)
Canvas
canvas;
Pixwin *
pw;
Rectlist *
repaint_area;
int width
= (int)window_get(canvas
int height
= (int)window get(canvas
int margin
= 10;
int xleft
= margin;
int xright
= width - margin;
int ytop
= margin;
int ybottom
= height - margin;
CANVAS_WIDTH);
CANVAS_HEIGHT) ;
/* draw box */ k
pw_vector(pw, xleft, ytop, xright, ytop, PIX_SRC, 1);
pw__vector (pw, xright, ytop, xright, ybottom, PIX_SRC, 1);
pw_vector(pw, xright, ybottom, xleft, ybottom, PIX_SRC, 1);
pw_vector(pw, xleft, ybottom, xleft, ytop, PIX_SRC, 1);
/* draw diagonals */
pw_vector(pw, xleft, ytop, xright, ybottom, PIX_SRC, 1);
pw_vector(pw, xright, ytop, xleft, ybottom, PIX_SRC, 1);
#sun
Xr microsystems
Revision A, of May 9, 1988
Chapter 5 — Canvases 69
There are several points to note from the example on the previous page. First,
since the width and height of the canvas are not specified, they default to the
width and height of the window. Second, since the image being drawn is depen¬
dent on the size of the canvas, we set CANVAS_FIXED_IMAGE to FALSE.
Third, when the repaint proc is called, we don’t bother to draw the specified
repaint area, instead we rely on the clipping list to be restricted correctly and
simply redraw the entire image.
5.6. Automatic Sizing of Two attributes requiring some explanation are CANVAS_AUTO_EXPAND and
the Canvas CANVAS_AUTO_SHRiNK. Setting both these attributes to true allows you to
have a drawing area which automatically tracks the size of the window.
If CANVAS_AUTO_EXPAND is TRUE, the canvas width and height are never
allowed to be less than the edges of the canvas pixwin. For example, if you try to
set CANVAS_WIDTH to a value which is smaller than the width of the canvas
pixwin, the value will be automatically expanded (rounded up) to the width of
the canvas pixwin.
The main use of CANVAS_AUTO_EXPAND is to allow the canvas to grow bigger
as the user stretches the window. For example, if the canvas starts out exactly
the same size as the canvas pixwin, and the user stretches the window, the canvas
pixwin will get bigger, which will cause the canvas itself to expand.
Another point to keep in mind is that whenever you set
CANVAS_AUT0_EXPAND to TRUE, the canvas will be expanded to the edges of
the canvas pixwin (if it is smaller to begin with).
CANVAS_AUTO_SHRINK is symmetrical to CANVAS_AUTO_EXPAND. If
CANVAS_AUTO_SHRINK is TRUE, the canvas width and height are never
allowed to be greater than the edges of the canvas pixwin.
NOTE As described in Section 4.8, Attribute Ordering, the canvas attributes are
evaluated before the generic window attributes. This means that, if you want to
set the window size and then disable automatic sizing of the canvas, you must
first set the window size, then, in a separate window_set () call, disable
CANVAS_AUTO_S HRINK and/or CANVAS_AUTO_EXPAND. If you do both in
the same call, the auto-sizing will be turned off before the window size is set, so
the canvas size will not match the window size you specify. Here is an example
of how to do it correctly:
r - - --—--\
canvas = window_create(frame, CANVAS,
WIN_HEIGHT, 400,
WIN_WIDTH, 600,
0 );
window_set(canvas,
CANVAS_AUTO_SHRINK, FALSE,
CANVAS_AUTO_EXPAND, FALSE,
0 );
^
microsystems
Revision A, of May 9, 1988
70 SunView 1 Programmer’s Guide
5.7. Handling Input in This section gives some hints on basic handling of input in canvases. 24
Canvases
Default Input Mask By default, canvases enable LOC_WlNENTER, LOC_wiNEXIT, LOC_MOVE and
the three mouse buttons, MS__LEFT, MS_MIDDLE and MS_RIGHT. 2 - 5
NOTE Since the canvas pixwin is actually a region of the subwindow’s pixwin, your
event procedure will receive LOC_RGNENTER and LOC_RGNEXIT events
rather than LOC_WINENTER and L0C_WINEXIT. The locator motion events
— LOC_MOVE, LOC_STILL, LOC_DRAG, and LOC_TRAJECTORY —will
only be passed to your event procedure if they fall within the canvas pixwia
You can enable events other than those listed above with the window attributes
applying to events. So, for example, you could allow the user to type in text to a
canvas by calling:
----
window_set(canvas, WIN_CONSUME_KBD_EVENT, WIN_ASCII_EVENTS, 0);
s___/
An application needing to track mouse motion with the button down would
enable LOC_DRAG by calling:
- —— - >
window_set(canvas, WIN_CONSUME_PICK_EVENT, LOC_DRAG, 0);
« __ _/
Writing Your Own Event
Procedure
Translating Events from
Canvas to Window Space
If you supply an event procedure as the value of WIN_event_PROC, it will get
called when any event is received for the canvas. Before your event procedure
gets called, however, the canvas package does some processing. If the event is
WIN_REPAINT or WIN_RESIZE, the canvas package calls your repaint or
resize procedures if necessary. If the event is SCROLL_REQUEST, then the can¬
vas package performs the scroll. 26 The repaint, resize and scroll events are then
passed to your event procedure. In the case of events which have x-y coordi¬
nates, the canvas package translates the events from the coordinate space of the
canvas pixwin to that of the logical canvas.
Functions are provided to translate event coordinates from the coordinate space
of the canvas to the coordinate space of the canvas subwindow, and vice versa.
To go from canvas space to window space, use canvas_window_event ().
Keep in mind that the canvas_window_event function changes fields in its
event argument structure. For example, if you want to put up a menu in a canvas
24 The general input paradigm for Sunview is discussed in Chapter 6, Handling Input. See that chapter for a
full discussion of the available input events and how to use them.
25 Note that the canvas package expects to receive these events, and will not function properly if you disable
them. Also, if the user has the enabled the LeftJIanded option in the Input category of default sedit(l),
the mouse buttons are reversed: MS LEFT refers to the right mouse button, MS_RIGHT to the left mouse
button.
26 If you want write a procedure which is called before the repaint, resize or scroll event is processed by the
canvas package, in order to modify the interpretation of the event, you must interpose on the event, as described
in Chapter 17, The Notifier .
#sun
XT microsystems
Revision A, of May 9,1988
Chapter 5 — Canvases 71
subwindow, you need to specify the menu’s location in the coordinate of the
subwindow, not of the canvas.
To go from window space to canvas space, use canvas_event (). This
returns the Event * it is passed, with the x and y fields changed. The transla¬
tion is necessary if you read your own events with window_read_event () ,
described in the next chapter, Handling Input.
Border Highlighting
The SunView convention is that a subwindow indicates that it is accepting key¬
board events by highlighted its border. By default, canvas subwindows do not
enable any keyboard events, so the border is not highlighted. However, if you
explicitly enable keyboard events, by consuming WIN_ASCII_EVENTS, the
canvas package will highlight the canvas border when it is given the input focus.
Example 4:
The program below prints out the corresponding string when the user types 0,1,
or 2 into its canvas:
r i
#include <suntool/sunview.h>
#include <suntool/canvas.h>
static void my_event_j?roc () ;
main(argc, argv)
int argc;
char **argv;
{
Frame frame;
frame = window create(NULL, FRAME, 0);
window_create(frame, CANVAS,
WIN_CONSUME_KBD__E VENT, WIN_ASCI I_EVENTS ,
WIN EVENT PROC, my event_j?roc,
0) ;
window_main_loop (frame) ;
exit(0) ;
}
static void
my_event_j?roc (canvas, event)
Canvas canvas;
Event *event;
{
char *string = NULL;
switch ( event_action(event) ) {
case ' 0' :
string = "zero”;
break;
case '1':
string = "one ";
break;
i .- -J
W sun
\r microsystems
Revision A, of May 9, 1988
72 SunView 1 Programmer’s Guide
r
case ' 2' :
string = "two
break;
default:
break;
if (string != NULL)
pw_text(canvas^pixwin(canvas),
10, 10, PIX_SRC, NULL, string);
5.8. Color in Canvases
Setting the Colormap Segment
Color in Retained Canvases
Color in Scrollable Canvases
You can use color in canvases by specifying a colormap segment for the canvas
with the colormap manipulation routines described in Chapter 6, Handling Input.
The first thing to note is that since the canvas pixwin is a region of the
WIN_P IXWIN, you must also set the colormap segment for the canvas pixwin.
If the canvas is retained, then the colormap segment must be set before
CANVAS_RETAINED is set to TRUE. This is because the canvas package will
determine the depth of the backing pixrect based on depth of the colormap seg¬
ment defined for the WIN_P IXWIN. (If the colormap segment depth is greater
than two, then the full depth of the display will be used. Otherwise, the backing
pixrect depth will be set to one.)
Since the depth of the backing pixrect is determined when the canvas is created,
you must create the canvas with CANVAS_RETAINED false, then set the
colormap segment, then set CANVAS_RETAINED to TRUE.
If the canvas has scrollbars, you need to attach the scrollbars to the canvas after
the colormap segment has been changed. If the canvas has already been created
with scrollbars attached, you should change the colormap, then re-attach the
scrollbars. This will insure that the scrollbar pixwin regions use the new color-
map segment.
5.8. Color in Canvases
Setting the Colormap Segment
Color in Retained Canvases
Color in Scrollable Canvases
Revision A, of May 9, 1988
Chapter 5 — Canvases 73
Example 5:
Below is an example of setting the colormap segment for a canvas:
r -—--
♦include <suntool/sunview,h>
♦include <suntool/canvas.h>
♦include <sunwindow/cms rainbow.h>
init__color_canvas (base__f rame)
Frame basenframe;
{
{
Canvas canvas;
Pixwin *pw;
unsigned char red[CMS_RAINBOWSIZE];
unsigned char green[CMS_RAINBOWSIZE];
unsigned char blue[CMS_RAINBOWSIZE];
canvas = window_create (base__f rame, CANVAS,
CANVAS_RETAINED f FALSE,
0 );
cms_rainbowsetup(red, green, blue);
/* set the WIN_PIXWIN colormap */
pw = (Pixwin *) window_get(canvas, WIN_PIXWIN);
pw_setcmsname(pw, CMS_RAINBOW);
pw_putcolormap(pw, 0, CMS_RAINBOWSIZE, red, green, blue);
/* set the CANVAS_PIXWIN colormap */
pw = (Pixwin *) canvas_pixwin(canvas);
pw_s et cmsname(pw, CMS_RAINBOW);
pw_j>utcolormap(pw, 0, CMS_RAINBOWSIZE, red, green, blue);
window_set(canvas,
CANVAS_RETAINED, TRUE,
WIN__VERTICAL_SCROLLBAR, scrollbar__create (0) ,
WIN_H0RIZONTAL_SCROLLBAR, scrollbar_create(0),
0 );
}
}
V_
Revision A, of May 9, 1988
Handling Input
Handling Input. 77
6.1. An Overview of the Input Environment. 79
How are events generated ?. 79
What does the Notifier do with these events ?. 80
How do windows determine which input they will receive?. 80
6.2. Events. 80
An event Procedure. 80
How Subwindows Handle Events. 81
6.3. A List of Events. 81
Keyboard Motions. 85
6.4. Classes of Events. 86
ASCII Events . 86
Locator Button Events. 86
Locator Motion Events. . 86
Window Events. 87
Function Key Events...;. 88
Shift Key Events. 89
Semantic Events. 89
Other Events. 89
6.5. Event Descriptors. 90
6 . 6 . Controlling Input in a Window. 90
Input Focus. 91
Input Mask... 91
Determining which Window will Receive Input. 92
6.7. Enabling and Disabling Events . 93
Which Mask to Use. 93
Setting the Input Mask as a Whole. 95
Querying the Input Mask State. 95
6.8. Querying and Setting the Event State. 96
6.9. Releasing the Event Lock... 97
6.10. Reading Events Explicitly . 97
Handling Input
Material Covered
Header Files
Related Documentation
Summary Listing and Tables
This chapter explains how input is handled in SunView. Specifically it:
o gives an overview on how input is handled in SunView
□ describes events and how they are used;
□ gives various classes of events — Ascn, action events, function keys, locator
buttons, locator motion, window generated events, and so on;
□ explains the input focus model distinguishing between pick and keyboard
focuses;
□ shows how to control where input is distributed using input masks',
□ shows how to query the state of an event;
□ shows how to explicitly read events.
The material in this chapter applies to the window system as a whole. However,
it is of special interest to alerts or clients of canvases, who typically will want to
handle events themselves.
The definitions necessary to use SunView’s input facilities are in the header file
<sunwindow/win_input. h>, which is included by
<sunwindow/window_hs. h>, which in turn is included by default when
you include <suntool/sunview.h>.
The chapter titled Workstations in the SunView 1 System Programmer’s Guide
explains the input system at a lower level, covering such topics as how to add
user input devices to SunView.
To give you a feeling for what you can do with events, a list of the available
event descriptors and input related window events is given on the following page.
Many of these are discussed in the rest of this chapter and elsewhere (use the
Index to check). All are briefly described with their arguments in the input sum¬
mary tables in Chapter 19, SunView Interface Summary :
□ the Event Descriptors table begins on page 333;
□ the Input-Related Window Attributes table begins on page 334.
microsystems
77
Revision A, of May 9,1988
78 SunView 1 Programmer’s Guide
Input-Related Window Attributes
WIN_INPUT_DESIGNEE
WIN_CONSUME_KBD_EVENTS
WIN_GRAB_ALL_INPUT
WIN_IGNORE_KBD_EVENTS
WIN_KBD_FOCUS
WIN_CONSUME_PICK_EVENT
WIN_KBD_INPUT_MAS K
WIN_IGNORE_PICK_EVENT
WINJPICK_INPUT_MASK
WIN_CONSUME_PICK_EVENTS
WIN_CONSUME_KBD_EVENT
WIN_IGNORE_PICK_EVENTS
WIN_IGNORE_KBD_EVENT
Event Descriptors
WIN_NO_EVENTS
WIN_RIGHT_KEYS
WIN_ASCII_E VENTS
WIN_TOP_KEYS
WIN_IN_TRANSIT_EVENTS
WIN_UP_ASCII_EVENTS
WIN_LEFT_KEYS
WIN_UP_EVENTS
WIN_MOUS E_BUTTONS
msun
XT microsystems
Revision A, of May 9, 1988
Chapter 6 — Handling Input 79
6.1. An Overview of the The input environment for SunView differs from UNIX programs. Most UNIX
Input Environment programs read characters from standard input by using either the read(2) system
call or the standard I/O functions such as getc(3S), gets(3S), or scanf(3S).
SunView is different in that the underlying Notifier formats user input into uni¬
form events, which it distributes to the window’s event procedure.
How are events generated ? Figure 6-1 illustrates how events are generated and handled in SunView.
Figure 6-1 Input Events
Revision A, of May 9, 1988
80 SunView 1 Programmer’s Guide
What does the Notifier do with
these events ?
Events are generated from several sources. These include standard devices such
as the keyboard and mouse, special input devices such as graphics tablets, and
the window system itself.
SunView does not directly receive events from the hardware devices. Instead
each user action is interpreted by a “virtual” user input device (VUID) interface.
This interface packages the data it receives into an event and sends it to the appli¬
cation process. 27
The Notifier weaves events from all of these sources into a single, ordered event
stream. This event stream eliminates the need for the application to poll separate
streams from the different devices.
Because the underlying Notifier multiplexes the input stream between windows,
each individual window operates under the illusion that it has the user’s full
attention. That is, it sees precisely those input events that the user has directed to
it.
How do windows determine
which input they will receive?
Each window indicates which events it is prepared to handle using input masks ,
described in Section 6.6, Controlling Input in a Window. These masks only let
specified events through to the process.
6.2. Events
As discussed in the previous section, each user action generates an input event.
This event is passed to your event procedure as an Event pointer (type
Event *). Three types of information are encoded as part of an event:
□ an identifying code, accessed with the macro event_act ion ()
□ the location of the event in the window’s coordinate system, accessed with
the macros event_x () and event_y ()
□ a timestamp, accessed with the macro event_time ()
Notice that the macro event_action () has replaced the old event_id ().
For compatibility reasons, event_id () is still supported, so that old code that
does not use the new action event codes will still work. See Section 6.4, Classes
of Events, for an explanation of action events. New programs that want to take
advantage of the new action events must use the event_act ion () macro.
An event Procedure
Use the following form to specify an an event procedure in your applications:
void
sample event_proc(window, event, arg)
Window window;
Event *event;
caddr_t arg;
27 It is possible to bypass the VUID and receive unencoded events. Refer to the section on Unencoded Input
in Chapter 7 of the SunView 1 System Programmer s Guide.
Asun
XT microsystems
Revision A, of May 9, 1988
Chapter 6 — Handling Input 81
How Subwindows Handle
Events
6.3. A List of Events
The arguments passed in are the window, the event, and an optional argument
containing data pertaining to the event. For example, if the event is a
SCROLL_REQUEST, arg will be the scrollbar that sent the event.
The canvas and panel subwindows pass events that they receive on to an event
procedure. These event procedures are supplied by the application as the value
of WlN_EVENT_PROC. If you set the WlN_EVENT_PROC of a canvas or panel
to a function you have written, you can receive events after they have been pro¬
cessed by the canvas or panel. Both the canvas and panel packages process
SCROLL_REQUEST, WIN_RESIZE, and WIN_REPAINT events before calling
your event procedure. The form of an event procedure is:
void
sample__event_proc (window , event, arg)
Window window;
Event event;
caddr__t arg;
The arguments passed in are the window (canvas or panel), the event, and an
optional argument containing data pertaining to the event. For example, if the
event is a SCROLL_REQUEST, arg will be the scrollbar that sent the event.
The default panel event procedure maps events to actions and determines which
panel item to send the event to. The default canvas event procedure does no
further processing of the event. You can call the default window event procedure
by calling window_def ault event_proc () with the same arguments
passed to your event procedure.^
Two tables are given on the following pages. Table 6-1, Event Codes, lists the
predefined event codes and their values. 29 The event id or code numbers that the
window system uses to represent an event are included in this table. These event
code numbers are in the range of 0-65535. The numbers are useful when debug¬
ging a program because the debugger reports event codes as decimal integers and
not as names.
Table 6-2, Keyboard Motions and Accelerators, lists the event name and its asso¬
ciated keyboard accelerator.
28 If you need to receive an event before it is processed by a canvas, panel, or any other type of window, you
can use the more general notifier interposition mechanism described in Chapter 17, The Notifier ,
29 The same table also appears in the input summary section of Chapter 19, SunView Interface Summary.
\r microsystems
Revision A, of May 9, 1988
82 SunView 1 Programmer’s Guide
Table 6-1 Event Codes
Event Code
Description
Value (for debugging)
ASCII FIRST
Marks beginning of ASCII range
0
ASCII LAST
Marks end of ASCII range
127
META FIRST
Marks beginning of META range
128
META_LAST
Marks end of META range
255
ACTION ERASE CHAR BACKWARD
Erase char to the left of caret
31744
ACTION ERASE CHAR FORWARD
Erase char to the right of caret
31745
ACTION ERASE WORD BACKWARD
Erase word to the left of caret
31746
ACTION ERASE WORD FORWARD
Erase word to the right of caret
31747
ACTION ERASE LINE BACKWARD
Erase to the beginning of the line
31748
ACTION_ERASE_LINE_END
Erase to the end of the line
31749
ACTION GO CHAR BACKWARD
Move the caret one character to the left
31752
ACTION GO CHAR FORWARD
Move the caret one character to the right
31753
ACTION GO WORD BACKWARD
Move the caret one word to the left
31754
ACTION GO WORD END
Move the caret to the end of the word
31756
ACTION GO WORD FORWARD
Move the caret one word to the right
31755
ACTION GO LINE BACKWARD
Move the caret to the start of the line
31757
ACTION_GO_LINE_END
Move the caret to the end of the line
31759
ACTION_GO_LINE_FORWARD
Move the caret to the start of the next line
31758
ACTION_GO_COLUMN_BACKWARD
Move the caret up one line,
maintaining column position
31761
ACTION_GO_COLUMN_FORWARD
Move the caret down one line,
maintaining column position
31762
ACTION_GO_DOCUMENT_START
Move the caret to the beginning of the text
31763
ACTION_GO_DOCUMENT_END
Move the caret to the end of the text
31764
ACTION_STOP
Stop the operation
31767
ACTION_AGAIN
Repeat previous operation
31768
ACT I ON_P ROP S
Show property sheet window
31769
ACTION_UNDO
Undo previous operation
31770
ACTION_FRONT
Bring window to the front of the desktop
31772
ACTION_BACK
Put the window at the back of the desktop
31773
ACTION_OPEN
Open a window from its icon form or close
if already open)
31775
ACTION_CLOSE
Close a window to an icon
31776
ACTION_COPY
Copy the selection to the clipboard
31774
ACTION_PASTE
Copy clipboard contents to the insertion point
31777
ACTION_CUT
Delete the selection, put on clipboard
31781
ACTION_COPY_THEN_PASTE
Copies then pastes text
31784
ACTION_FIND_FORWARD
Find the text selection to the right of the caret
31779
ACTION_FIND_BACKWARD
Find the text selection to the left of the caret
31778
ACTION_FIND_AND_REPLACE
Show find and replace window
31780
ACTION SELECT_FIELD_FORWARD
Select the next delimited field
31783
ACTION_SELECT_FIELD_BACKWARD
Select the previous delimited field
31782
msun
Xr microsystems
Revision A, of May 9,1988
Chapter 6 — Handling Input 83
Table 6-1 Event Codes — Continued
Event Code
Description
Value (for debugging)
ACT I ON_MATCHJDELI MI TER
Selects text up to a matching delimiter
31894
ACT I ON__QUOTE
Causes next event in the input stream to
pass untranslated by the keymapping system
31898
ACT I ON_EMP T Y
Causes the subwindow to be emptied
31899
ACTION_STORE
Stores the specified selection as a new file
31785
ACT I ON__LOAD
Loads the specified selection as a new file
31786
ACT I ON_GET_F ILENAME
Gets the selected filename
31788
ACTION_SET_DIRECTORY
Sets the directory to the selection
31788
ACTION_INCLUDE_FILE
Selects the current line (in pending-delete mode)
and attempts to insert the file described by that selection
31891
ACTION_CAP S_LOCK
Toggle caps lock state
31895
PANEL_EVENT_CANCEL
The panel or panel item is no longer “current”
32000
P ANEL_E VENT_MOVE__I N
The panel or panel item was entered
with no mouse buttons down
32001
PANEL_EVENT_DRAG_IN
The panel or panel item was entered with one or more
mouse buttons down
32002
SCROLL_REQUEST
Scrolling has been requested
32256
SCROLL_ENTER
Locator (mouse) has moved into the scrollbar
32257
SCROLL_EXIT
Locator (mouse) has moved out of the scrollbar
32258
LOC_MOVE
Locator (mouse) has moved
32512
LOC__STILL
Locator (mouse) has been still for 1/5 second
32513
LOC_WI NENTER
Locator (mouse) has entered window
32514
LOC_WINEXIT
Locator (mouse) has exited window
32515
LOC_DRAG
Locator (mouse) has moved while a button was down
32516
LOC_RGNENTER
Locator (mouse) has entered a region of the window
32519
LOC_RGNEXIT
Locator (mouse) has exited a region of the window
32520
LOCJTRAJECTORY
Inhibits the collapse of mouse motions; clients receive
LOC_TRA JECTORY events for every locator motion
the window system detects.
32523
WIN_REPAINT
Some portion of window requires repainting
32517
WIN_RESIZE
Window has been resized
32518
WIN_STOP
User has pressed the stop key
32522
KBD_REQUEST
Window is about to become the focus of keyboard input
32526
KBD_USE
Window is now the focus of keyboard input
32524
KBD_DONE
Window is no longer the focus of keyboard input
32525
SHIFT_LEFT
Left shift key changed state
32530
SHIFT_RIGHT
Right shift key changed state
32531
SHIFT__CTRL
Control key changed state
32532
SHIFT_META
Meta key changed state
32534
SHIFT_LOCK
Shift lock key changed state
32529
SHIFT_CAPSLOCK
Caps lock key changed state
32528
Revision A, of May 9,1988
84 SunView 1 Programmer’s Guide
Table 6-1
Event Codes — Continued
Event Code
Description
Value (for debugging)
BUT (i)
MS_LEFT
MS_MIDDLE
MS_RIGHT
Locator (mouse) buttons 1-10
Left mouse button
Middle mouse button
Right mouse button
BUT(l) is 32544
32544
32545
32546
KEY_LEFT(i)
KEY_RIGHT(i)
KEYJTOP(i)
Left function keys 1-15
Right function keys 1-15
Top function keys 1-15
KEY_LEFT (1) is 32554
KEY_RIGHT (1) is 32570
KEYJTOP (1) is 32586
#sun
\r microsystems
Revision A, of May 9, 1988
Chapter 6 — Handling Input 85
Table 6-2 Keyboard Motions and Accelerators
Command Token
SunView 4.0
SunView 3.x
ACTION_ERASE_CHAR_BACKWARD
f Delete 1
(Delete ]
ACTION_ERASE_CHAR_FORWARD
1 Shift-Delete 1
l Shift-Delete 1
ACT I ON_ERAS E_W ORD_B ACKWARD
iControl-Wl
l£snwvJ-wj
ACTION_ERASE_WORD_FORWARD
IShift-Control-W J
l Shift-Control-W I
ACTION_ERASE_LINE_BACKWARD
(Control-U 1
l Control-U 1
ACTION_ERASE_LINE_END
1 Shift-Control-U 1
1 Shift-Control-U 1
ACTION_GO_CHAR_BACKWARD
l Control-B 1 or ( Shift-Control-F 1 or
fRlol
ACTION_GO_CHAR_FORWARD
[ Control-F 1 or I Shift-Control-B 1 or
fRin
ACTION_GO_WORD_BACKWARD
(Control -comma 1 or
I Sbifl-ConlTol-Deriod ) or
[ Shift-Control-s/ayA)
ACT I ON__GO_WORD_END
l Control -period 1
ACTION_GO_WORD_FORWARD
(Control-s/as/t) or
[ Shift-Control-cewvra 1
ACTION_GO_LINE_FORWARD
l Control-semicolon ) or f Rll 1
ACTION_GO_LINE_BACKWARD
I Control-A 1 or l Shift-Control-E 1
ACT I ON_GO_LI NE_END
l Control-JEJ or [ Shift-Control-A)
ACT I ON_GO_COLUMN_BACKWARD
LCQD.lrgl-.EJ or [ Shift-Control-N) or
IrTTI
ACTION_GO_COLUMN_FORWARD
l Control-N J or 1 Shift-Control-P) or
IrTFI
ACTI ON_GO_DOCUMENT_START
(Shift-Control-Retum ) or [ R7 ]
ACTION__GO_DOCUMENT_END
I Control-Return 1 or [ R13 1
l Control-Return 1
ACTI ON_ST OP
fin
rm
ACTION_AGAIN
[ L2l or 1 Meta-k 1
rm
ACT I ON__PROP S
rm
rm
ACTION_UNDO
im or 1 Meta-U 1
rm
ACTION_FRONT
rm
rm
ACTION_BACK
1 Shift-L5 1
lShift-L5j
ACTION_OPEN
rm
rm
ACTION_CLOSE
I Shift-L71
[ Shift-L71
ACT I ON__COP Y
fL6) or 1 Meta-Cl
rm
ACTION_PASTE
fin or 1 Meta-V 1
ILL) or LCaniral-C J
ACTION_CUT
fOol orlMfW-X J
I.LHL) or l Control-D 1
ACT I ON_COP Y_THEN_P ASTE
1 Meta-? ]
(Control-P)
ACT I ON_F I ND_FORWARD
(m or I Meta-F1
( L9 1 or 1 Control-F 1
ACT I ON_F I ND_BACKWARD
1 Shift-L9 1 or [ Shift-Meto-F 1
l Shift-L9 lor l Shift-Control-F 1
ACTION_FIND_AND_REPLACE
1 Control-L9 1
ACTION_SELECT_FIELD_FORWARD
IConnai-TabJ
ACTION_SELECT_FIELD_BACKWARD
LShift-CQnirQl-Ia!? J
ACT I ON__MATCH_DELI MI TER
I Meta-D )
ACTION_QUOTE
1 Meta-O )
ACTION_EMPTY (Document)
l Mela- E 1
ACT I ON__STORE
1 Meto-S)
microsystems
Revision A, of May 9,1988
86 SunView 1 Programmer's Guide
Table 6-2 Keyboard Motions and Accelerators — Continued
Command Token
SunView 4.0
SunView 3.x
ACTION_LOAD
I Meta- LI
ACTION_INCLUDE_FILE
I Meta-l I
ACTION_HELP 30
l Meta-1 J (l Mefa-ShiftZ!)
ACTION_GET_FILENAME
[ Escape)
l Escape. J
ACTION_CAPS_LOCK
rm
rm
6.4. Classes of Events
ASCT Events
Locator Button Events
Locator Motion Events
This section groups each of the events described in Table 6-1, Event Codes, into
logical classes. Each class is described below.
The event codes in the range 0 to 255 inclusive are assigned to the ASCII event
class. This includes the standard 7-bit ASCII codes and their 8-bit META coun¬
terparts.
If a user strikes a key which has an obvious ASCII meaning; that is, a key in the
main typing array labeled with a single letter, it causes the VUID to enqueue for
the appropriate window an event whose code is the corresponding 7-bit ASCII
character.
The META event code values (128 through 255) are generated when the user
strikes a key that would generate a 7-bit ASCII code while the META key is also
depressed.
The standard Sim locator is a three button mouse, whose buttons generate the
event codes MS_LEFT, MS_MIDDLE and MS_RIGHT.
In general, a physical locator can have up to 10 buttons connected to it. In some
cases, the locator itself may not have any buttons on it; however, it may have
buttons from another device assigned to it. A light pen is an example of such a
locator.
Each button that is associated with the VUID’s locator is assigned an event code;
the i-th button is assigned the code BUT ( i ). Thus the event codes MS_LEFT,
MS_MIDDLE and MS_RIGHT correspond to BUT (1), BUT (2) and BUT (3).
The physical locator constantly provides an (x, y) coordinate position in pixels;
this position is transformed by SunView to the coordinate system of the window
receiving an event. Locator motion event codes include LOC_MOVE,
LOC_DRAG, LOC_TRAJECTORY, and LOC_STILL.
Since the locator tracking mechanism reports the current position at a set sam¬
pling rate, 40 times per second, fast motions will yield non-adjacent locations in
consecutive events.
30 If your keyboard has the IL161 key, you may also use it.
Revision A, of May 9,1988
Chapter 6 — Handling Input 87
Window Events
Resize & Repaint Events
A LOC_MOVE event is reported when the locator moves, regardless of the state
of the locator buttons. If you only want to know about locator motion when a
button is down, then enable LOC_DRAG instead of LOC_MOVE. This will
greatly reduce the number of motion events that your application has to process.
When you enable LOC_MOVE or LOC_DRAG, the window system gives you the
current locator position by collapsing consecutive locator motion events into one.
This operation is appropriate for applications such as dragging an image from
one point to another, in which it is important to keep up with the mouse cursor.
For some applications, however, each point on the cursor trajectory is of interest;
for example, a program that lets the user draw. In these situations you may not
want to collapse consecutive motion events. In such a situation you should ask
for LOC_TRA JECTORY events, which suppresses any event collapsing so that
you get all the locator movements that the window system sees.
Note that when you ask for LOC_TRAJECTORY events, you get (many!)
LOC_TRA JECTORY events in place of LOC_MOVE’s, but you still get
LOC_drag events if you have enabled them.
If you ask for LOC_STILL, a single L0C_STILL event will be reported after
the locator has been still for 1/5 of a second.
Window events are generated by the window system itself. They are meaningful
only to the window to which they are directed.
To be informed when the locator enters or exits a window, enable events with the
codes LOC_WINENTER and LOC_WINEXIT.
NOTE If you are using the tile mechanism described in the S unView 1 System
Programmer’s Guide, then you will be told when the locator has entered or
exited a tile using the LOC_RGNENTER and L0C_RGNEXIT events. To receive
these events you must also have LOC_MOVE enabled.
When the size of a window is changed (either by the user or programmatically) a
WIN_RESIZE event is generated to give the client a chance to adjust any
relevant internal state to the new window size. You should not repaint the screen
on receiving a resize event. You will receive a separate WIN_REPAINT event
when a portion of the window needs to be repainted.
NOTE If you are using a canvas subwindow you will not need to track resize and
repaint events directly. The canvas package receives these events, computes the
new window dimensions or the precise area requiring repainting, and calls your
resize or repaint procedures directly. See Chapter 5, Canvases for more details.
microsystems
Revision A, of May 9, 1988
88 Sun View 1 Programmer’s Guide
Keyboard Focus Events
Stop Event
Function Key Events
Three events let your application interact with the keyboard focus mechanism
(the keyboard focus is explained in section 6.6, Controlling Input in a Window ).
When the user explicitly directs the keyboard focus towards your window, you
will receive a KBD_REQUEST event. Your window will then become the key¬
board focus unless you call window_ref use_kbd_f ocus (). Refusing the
keyboard focus, when you don’t need it, contributes to the usefulness of the split
keyboard/pick focus mode available as a runtime option to sunview(l).
The events KBD_USE and KBD_DONE parallel the locator events
L0C_WINENTER and LOC_WINEXIT, respectively. KBD_USE indicates that
your window now has the keyboard focus and KBD_DONE indicates that your
window no longer has it.
If the user presses and releases the I Stop 1 key, an event with the code
WIN_STOP will be sent to the window under the cursor. 31 In addition, a
SIGURG signal is sent to the window’s process. Your application can use the
1 Stop I key by clearing a stop flag and setting a SIGURG interrupt handler 32
before entering a section of code that might, from the user’s perspective, take a
long time. If your SIGURG handler is called, set the stop flag and return. In the
code that is taking a long time, query the stop flag whenever convenient When
you notice that the stop flag has been set, read the event, then gracefully ter¬
minate your long operation.
The function keys in the VUID define an idealized standard layout that groups
keys by location: 15 left, 15 right, 15 top and 2 bottom. 33
The event codes associated with the function keys are KEY_LEFT (i),
KEY_RIGHT (i) and KEY_TOP (i) , where i ranges from 1 to 15.
If you specifically ask for a function key event code, then that event code will be
passed to your event procedure.
If you don’t specifically ask for a given function key event code, then when the
user presses that function key you will get an escape sequence instead of the
function key event code (assuming ASCII events have been enabled). For physi¬
cal keystations that are mapped to cursor control keys, events with codes that
correspond to the ANSI X3.64 7-bit ASCII encoding for the cursor control func¬
tion are transmitted. For physical keystations mapped to other function keys,
events with codes that correspond to an ANSI X3.64 user-definable escape
sequence are transmitted.
31 WIN_STOP only works when enabled in the PICK event mask and not in the KBD event mask.
32 See notify_set_signal_func () in in Chapter 17, The Notifier
33 The actual position of the function keys on a given physical keyboard may differ — see kbd(5) for details
on various keyboards.
microsystems
Revision A, of May 9, 1988
Chapter 6 — Handling Input 89
Shift Key Events
Semantic Events
Other Events
Applications can notice when a shift key changes state by enabling events with
the following codes: SHIFT_LEFT, SHIFT_RIGHT, SHIFT_CTRL,
SHIFT_META, SHIFT_L0CK and SHlFT_CAPSLOCK. Although these codes
allow you to treat one or more shift key as function-invoking keys, this is not
recommended. Instead of watching for the event directly, you should query the
state of the shift keys via the macros described on the next page.
Release 4.0 of the SunOS introduces a new type of event. These events are
called action events and represent some old and many new functions in the win¬
dow system. They are similar to the old events in that they are mapped to
specific keys on the keyboard. That is, certain combinations of keystrokes in
SunView correspond to high-level action events. For example, pressing the
1 Copy ] key copies the current selection to the Clipboard in text subwindows,
panels and tty subwindows.
Action events differ from the old events in that applications can directly express
interest in the high-level action, “Copy the selection to the Clipboard” rather than
in the low-level, “The L6 key was pushed”. These events appear in Table 6-1
with the prefix ACTI0N_. Applications should use action events, because left-
handed users can assign I Copy I to a different key, and in the future users will be
allowed to tie high-level events to arbitrary key combinations.
Your application may receive events which don’t fall into any of the classes
described above. For example, a non-standard input device, such as a second
mouse, may emit its own types of events. Also, a software object may communi¬
cate with other software objects via events, as is the case when a scrollbar sends a
SCROLL_REQUEST to a panel or a canvas.
In general, your event procedure should not treat such unexpected events as
errors. They can simply be ignored.
microsystems
Revision A, of May 9, 1988
90 SunView 1 Programmer’s Guide
6.5. Event Descriptors Events have been further grouped into descriptors. Descriptors describe classes
of events such as all ASCII events, all mouse buttons, all top function keys, and
so on. You will use these descriptors to set input masks, described in Section 6.7
Enabling and Disabling Events
The descriptors are summarized in the following table.
Table 6-3 Event Descriptors
Event Descriptor
Explanation
WIN_NO_EVENTS
Clears input mask — no events will be accepted. Note: the
effect is the same whether used with a consume or an
ignore attribute. A new window has a cleared input mask.
WIN_ASCII_EVENTS
All ASCD events. ASCII events that occur while the META
key is depressed are reported with codes in the META range.
In addition, cursor control keys and function keys are
reported as ANSI escape sequences: a sequence of events
whose codes are ASCII characters, beginning with <ESC>.
WIN_IN_TRANSIT_EVENTS
Enables immediate LOC_MOVE,
LOCJWINENTER, and
LOC__WINEXIT events. Pick mask only. Off by default
WIN_LEFT_KEYS
The left function keys, KEY_LEFT(1) — KEY_LEFT(15).
WIN_MOUSE_BUTTONS
Shorthand for MS_RIGHT,
MS_MIDDLE
and MS_LEFT.
Also sets or resets WIN_UP__E VENTS.
WIN_RIGHT_KEYS
The right function keys, KEY_RIGHT(1) — KEY_RIGHT(15).
WIN_TOP_KEYS
The top function keys, KEY_TOP(l) — KEY_TOP(15).
WIN_UP_ASCII_EVENTS
Causes the matching up transitions to normal
ASCII events to be reported — if you see an ’a’
go down, you’ll eventually see the matching *a’ up.
WIN_UP_EVENTS
Causes up transitions to be reported for button
and function key events being consumed.
Input may be controlled using input focus and input mask. The input focus is the
window that is currently receiving input. The input mask specifies which events
a window will receive and which events a window will ignore. This section
introduces these concepts and gives the algorithm used by the window system to
decide which window will receive a given input.
6.6. Controlling Input in a
Window
XT microsystems
Revision A, of May 9,1988
Chapter 6 — Handling Input 91
Input Focus
Input Mask
SunView supports two types of focus models, a single focus model and a split
focus model.
The single focus model specifies that all input, no matter which input device it
came from, goes to the same window. The split input focus lets the user control
the pick input focus and the keyboard input focus separately.
The word pick comes from the general graphics term pick device, which is a user
input device that allows you to move a cursor on the screen and then click a but¬
ton to choose a point on the screen. The most common pick devices are the
mouse, light pen and graphics tablet.
Under the split input focus model, mouse clicks and keystrokes may be distri¬
buted to different windows. This makes some operations easier for the user. For
example, the user can select text in one window and move it to another window
without having to position the cursor over the destination window.
In general, the user controls the keyboard focus by using specific button clicks
and controls the pick focus by moving the mouse. Sometimes, it is appropriate
for input focuses to be under program control. Generally you should only change
an input focus based on some explicit and predictable user action.
You can indicate that you want a window to become the keyboard focus by set¬
ting the WlN_KEYBOARD_FOCUS attribute to TRUE. Note that this is only a
hint to the window system. If the keyboard focus is tied to the pick focus, then
this call has no effect. The target window might also refuse the keyboard focus
request generated by this call (see KBD_REQUEST under Window Events above).
You can set the pick focus via the wiN_MOUSE_XY attribute, which sets the
mouse cursor to a particular position within a window.
For example, the call
- \
window_set(win, WIN_MOUSE_XY f 200, 300, 0);
V____y
sets the cursor to the window-relative position (200, 300) and sets the pick focus
to win.
An input mask specifies which events a window will receive and which events it
will ignore. In other words, an input mask serves as a read enable mask. Each
window has both a pick input mask, to specify which pick related events it wants,
and a keyboard input mask, to specify which keyboard related events it wants.
When a window is the pick focus, its pick mask is used to screen events. When a
window is the keyboard focus, its keyboard mask is used to screen events.
This section describes how to specify which events a window will receive and
which it will ignore.
microsystems
Revision A, of May 9,1988
92 SunView 1 Programmer’s Guide
Determining which Window
will Receive Input
The Notifier determines which window will receive a given event according to
the following algorithm:
□ First, the keyboard input mask for the window which is the keyboard focus
is checked to see if it wants the event. If so, then it becomes the recipient;
otherwise the next test is applied.
□ Second, the pick input mask for the window which is under the cursor is
checked to see if it wants the event. If several windows are layered under
the cursor, then the event is tested against the pick input mask of the topmost
window. If the mask wants the event, then it becomes the recipient; other¬
wise the next test is applied.
□ If the event does not match the pick input mask of the window under the cur¬
sor, then the event will be offered to that window’s designee. By default the
designee is the window’s owner. You can set the designee explicitly by cal¬
ling window_set () with the WIN_INPUT_DESIGNEE attribute. 34
□ If an event is offered unsuccessfully to the root window, it is discarded.
Windows which are not in the chain of designated recipients never have a
chance to accept the event.
□ Occasionally you may want to specify that a given window is to receive all
events, regardless of their location on the screen. You can do this by setting
the WIN_GRAB_ALL_INPUT attribute for the window to TRUE.
□ If a recipient is found, then the locator coordinates are adjusted to the coor¬
dinate system of the recipient, and the event is appended to the recipient’s
input stream. Thus, every window sees a single ordered stream of time-
stamped input events, which contain only the events that a window has
declared to be of interest
34 Note that you must give the WIN DEVICE NUMBER of the window you wish to be the designee, not its
handle. This is to allow specifying windows in another user process as the input designee. So the following call
would set win2 to be the designee for win 1: window_set (winl, WIN_INPUT_DESIGNEE,
window_get (win2, WIN_DEVICE_NUMBER) ) ;
Revision A, of May 9, 1988
Chapter 6 — Handling Input 93
6.7. Enabling and You specify which events a window will receive and which it will ignore by set-
Disabling Events ting the window’s input masks via the following set of attributes:
Table 6-4 Attributes Used to Set Window Input Masks
Events Taking a
Single Code
Events Taking a Null
Terminated List
WI N_C ON S UME_KBD_E VEN T
WlN_CONSUME_KBD_EVENTS
WI N_I GNORE_KBD_EVENT
WIN_IGNORE_KBD_EVENTS
WIN_CONSUME_PICK_EVENT
WIN_CONSUME_PICK_EVENTS
WIN_IGNORE_PICK_EVENT
WIN_IGNORE_PICK_EVENTS
The above attributes take as values either event codes such as LOC_MOVE,
MS_LEFT, KEY_LEFT ( 2 ), and so on, or event descriptors. The attributes in
the left column, ending in “_EVENT”, take a single code or descriptor, while
those on the right, ending in “_EVENTS”, take a null terminated list
Which Mask to Use To enable or disable ASCII events, use the keyboard mask. To enable or disable
locator motion and button events, use the pick mask.
Function keys are typically associated with the keyboard mask, but sometimes it
makes sense to include some function keys in the pick mask — in effect extend¬
ing the number of buttons associated with the pick device. For example, in the
SunView interface the (Again I . 1Undo) . 1 Copy 1 . 1 Paste I . (Tutl . and rFIndl func¬
tion keys are associated with the keyboard mask, while the I Stop 1 . 1 Front I . and,
1 Open I keys are associated with the pick mask.
Examples The event attributes cause precisely the events you specify to be enabled or dis¬
abled — the input mask is not automatically cleared to an initial state. To be
sure that an input mask will let through the events you specify, first clear the
mask with the special WlN_NO_EVENTS descriptor. Take, for example, the fol¬
lowing two calls:
window_set(win, WIN_CONSUME_PICK_EVENTS,
WIN_MOUSE_BUTTONS, LOC_DRAG, 0,
0 ) ;
window_set(win, WIN_CONSUME_PICK_EVENTS,
WIN_NO_EVENT S, WIN_MOUSE_BUTTONS, LOC_DRAG, 0,
0 ) ;
The first call adds the mouse buttons and LOC_DRAG to the existing pick input
mask, while the second call sets the mask to let only the mouse buttons and
LOC_DRAG through.
V microsystems
Revision A, of May 9,1988
94 SunView 1 Programmer’s Guide
Canvases by default enable loc_winenter, loc_winexit, loc_move,
and the three mouse buttons, MS_LEFT, MS_MIDDLE, and MS_RIGHT. 33 You
could allow the user to type in text to a canvas by calling:
r -- “ >
window_set(canvas, WIN_CONSUME_KBD_EVENT, WIN_ASCII_EVENTS, 0) ;
< _. _'
Sometime later you could disable type-in by calling:
----
window set (canvas, WIN_IGNORE_KBD_EVENT, WIN_ASCII_EVENTS, 0);
An application needing to track mouse motion with the button down would
enable LOC_DRAG by calling:
You can enable or disable the left, right or top function keys as a group via the
event descriptors win_LEFT_KEYS, win_RIGHT_keys, or
WIN TOP_KEYS. Note that if you want to see the up event you must also ask
for WIN UP EVENTS, as in:
In order to improve interactive performance, in the default case, windows do not
receive locator motion events (LOC_wiNENTER, LOC_WINEXIT, and
LOC_MOVE) until after a L0C_STILL has been generated. If each window
responds to all of the events that are generated each time the mouse passes over
the window, then the response time of the system will be slowed down. Each
window will “wake up” when the mouse passes over it on the way to somewhere
else on the screen.
If you want a window to receive all events, even if the mouse is just passing over
the window without stopping, enable WIN_IN_TRANSIT_EVENTS, with a call
such as:
35 Note that the canvas package expects to receive these events, and will not function properly if you disable
them.
»SIU1
Xr microsystems
Revision A, of May 9,1988
Chapter 6 — Handling Input 95
Setting the Input Mask as a The attributes WIN_KBD_INPUT_MASK and WIN_PICK_INPUT_MASK allow
Whole you to get or set an entire input mask. Let’s take the example of a subroutine that
provides interactive feedback. You can save the input mask on entry to the sub¬
routine, set up the mask as appropriate, and restore the original mask before
returning as follows:
( -—-
do_feedback()
{ "
Inputmask *saved_mask;
saved_mask = (Inputmask *)
window_get(win, WIN_KBD_INPUT_MASK);
window_set(win, WIN_KBD_INPUT_MASK, saved_mask, 0);
Keep in mind that the inputmask pointer returned by window_get () points to
a static structure which is shared by all windows in the application. Getting
either the keyboard or pick input masks for another window will cause the static
structure to be overwritten.
Querying the Input Mask
State
You can use window_get () with WlN_CONSUME_PICK_EVENT and
W IN_C0NS UME_KBD_E VENT to query the state of the input masks. For exam¬
ple, the following call will find out whether or not a canvas is accepting
LOC_DRAGs:
/-\
flag * (int) window_get (canvas, WIN_CONSUME_PICK_EVENT, LOC_DRAG) ;
V_y
microsystems
Revision A, of May 9, 1988
96 SunView 1 Programmer’s Guide
6.8. Querying and Setting You can query the state associated with an event using the following macros, all
the Event State of which take as their only argument a pointer to an Event.
Table 6-5 Macros to Get the Event State
Macro
Returns
event_action ()
The identifying code of the event The codes are dis¬
cussed in the previous section. 36
event_is_up ()
TRUE if the event is a button or key
event and the state is up.
event__i s_down ()
TRUE if the event is a button or key
event and the state is down.
event__x ()
The x coordinate of the locator in the window’s
coordinate system at the time the event occurred.
event_y()
The y coordinate of the locator in the window’s
coordinate system at the time the event occurred.
event_shiftmask()
The value of predefined shift-keys
(described in kbd(5)). Possible values:
#define CAPSMASK 0x0001
#define SHIFTMASK OxOOOE
#define CTRLMASK 0x0030
#define META__SH IFT__MASK 0x0040
event_time()
The event’s timestamp, formatted as a timeval
struct, as defined in <sys/time .h>.
event_shift_is_down ()
TRUE if one of the shift keys are down.
event_ct rl_i s_down ()
TRUE if the control key is down.
event_meta_is_down ()
TRUE if the meta key is down.
event__i s_button ()
TRUE if the event is a mouse button.
event_is_ascii ()
TRUE if the event is in the ASCII range (0 thru 127).
event_is__meta ()
TRUE if the event is in the META range (128 thru 255).
event_is__key__left ()
TRUE if the event is any KEY_LEFT (i).
event_i s_key_right ()
TRUE if the event is any KEY_RIGHT (i).
event_i s_key_top ()
TRUE if the event is any KEY_TOP (i).
In addition to the above macros, which tell about the state of a particular event,
you can query the state of any button or key via the WIN_EVENT_STATE attri¬
bute. For example, to find out whether or not the first right function key is down
you would call:
---— - — - >
kl_down = (int)
window_get(canvas, WIN_EVENT_STATE, KEY_RIGHT(1));
s__—- '
The call will return non-zero if the key is down, and zero if the key is up.
The following macros are provided to let you set some of the states associated
with an event.
36 event_id() is replaced by event_act ion () However, for compatibility, event_id () will still
be supported.
Revision A, of May 9, 1988
Chapter 6 — Handling Input 97
Table 6-6 Macros to Set the Event State
Macro
Effect
event_set__action (event, code)
event_set__shiftmask
set event’s id to code.
(event, shiftmask)
set event’s shiftmask to shiftmask.
Possible values:
#define CAPSMASK
0x0001
#define SHIFTMASK
OxOOOE
#define CTRLMASK
0x0030
#define META__SHIFT_MASK
0x0040
event__set_x (event, x)
set event’s x coordinate to x.
event_set_y(event, y)
set event’s y coordinate to y.
event_set_time(event, time)
set event’s timestamp to time.
event_set_up(event)
set state of a button event to up.
event_set_down(event)
set state of a button event to down.
6.9. Releasing the Event If an operation generated by an input event is going to take over 5 seconds, then
Lock call this routine to allow other processes to get input: 37
void
window_release__event_lock (window)
Window window;
6.10. Reading Events There are times when it is appropriate to go get the next event yourself, rather
Explicitly than waiting for it to come through the normal event stream from the Notifier. In
particular, when tracking the mouse with an image which requires significant
computation, it may be desirable to read events until a particular action, such as a
mouse button up, is detected. To read the next input event for a window, bypass¬
ing the Notifier, use the function:
int
window__read_event (window f event)
Window window;
Event *event;
window_read_event () fills in the event structure, and returns 0 if all went
well. In case of error, it sets the global variable errno and returns —1.
window_read_e vent () can be used in either a blocking or non-blocking
mode, depending on how the window has been set up. 38
37 For more details see the section on synchronization in the Workstations chapter of the SunView 1 System
Programmer’s Guide.
38 window_read_event() is the high-level library standard function equivalent of input_readevent() in the
low-level library. For further information, see Section 5.6, Reading Input in the SunView 1 System
Programmer s Guide.
Revision A, of May 9, 1988
98 SunView 1 Programmer’s Guide
Note that if you read events in a canvas subwindow yourself, you must translate
the event’s location to canvas space by calling canvas_event ():
event_in_canvas_space = canvas_event(canvas, event);
Revision A, of May 9,1988
Imaging Facilities: Pixwins
Imaging Facilities: Pixwins. 101
7.1. What is a Pixwin?. 103
7.2. Accessing a Pixwin’s Pixels. 103
Obtaining the Window’s Pixwin. 103
Write Routines. 104
Basic RasterOp Operations. 104
Other Raster Operations. 104
Text Routines. 105
Batching and Stenciling Routines. 106
Drawing Polygons. 107
Drawing Curved Shapes. 107
Drawing Lines. 107
Read and Copy Routines. 108
7.3. Rendering Speed. 108
Locking. IO 9
Batching. HO
Locking and Batching Interaction. 112
7.4. Clipping With Regions. 112
7.5. Color. 113
Introduction to Color. - 113
The Colormap. H 3
Changing the Colormap. 114
Colormap Segments. 114
Background and Foreground. 115
Default Colormap Segment. 115
Changing Colors from the Command Line. 115
Sharing Colormap Segments. 115
Example: showcolor . 116
Manipulating the Colormap... 117
Cycling the Colormap. 118
Miscellaneous Utilities. 118
Using Color. 119
Cursors and Menus .. 119
Is My Application Running on a Color Display?. 119
Simulating Grayscale on a Color Display. 120
Software Double Buffering. 120
Hardware Double-Buffering. 122
7.6. Plane Groups and the cgf our Frame Buffer. 124
SunView and Plane Groups... 125
sunview and Plane Groups. 126
Imaging Facilities: Pixwins
Material Covered
This chapter describes the pixwin which is the construct you use to draw or
render images in SunView. The most basic use of pixwins is to draw in a canvas
subwindow.
In addition to basic pixwin usage, this chapter covers:
□ How to boost your rendering speed by locking and batching
□ How to use regions for clipping
□ How to manipulate the colormap
□ How to use the plane groups
Related Documentation
This chapter is addressed primarily to programmers who write simple applica¬
tions using canvas subwindows. For lower level details, see the chapter on
Advanced Imaging in the SunView System Programmers Guide.
The pixwin drawing operations do not directly support high-level graphics opera¬
tions such as shading, segments, 3-D, etc. If your application requires these, then
you should consider some graphics package such as SunGKS, SunCore, or
SunCGI. All of these will run in windows (see the SunCore Reference Manual
and SunCGI Reference Manual for more information).
Header Files
The definitions necessary to use pixwins are in the header file
<sunwindow/pixwin. h>, which is included by
<sunwindow/window_hs . h>, which in turn is included by default when
you include <suntool/sunview. h>.
Summary Listing and Tables
To give you a feeling for what you can do with pixwins, the following page con¬
tains a list of the available pixin functions and macros. Many of these are dis¬
cussed in the rest of this chapter and elsewhere (use the Index to check). All are
briefly described with their arguments in the pixwin summary tables in Chapter
19, SunView Interface Summary :
□ the Pixwin Drawing Functions and Macros table begins on page 356;
□ the Pixwin Color Manipulation Functions table begins on page 360.
microsystems
101
Revision A, of May 9, 1988
102 SunView 1 Programmer’s Guide
_ Pixwin Drawing Functions and Macros _
pw_batch(pw, n)
pw_batch_of f (pw)
pw_batch_on (pw)
pw_batchrop(pw, dx, dy, op, items, n)
pw_char(pw, x, y, op, font, c)
pw_close(pw)
pw_copy(dpw, dx, dy, dw, dh, op, spw, sx, sy)
pw__get (pw, x, y)
pw_get_region_rect (pw, r)
pw_line(pw, xO, yO, xl, yl, brush, tex, op)
pw__lock(pw, r)
pw_pfsysclose ()
pw_pfsysopen()
pw_jpolygon__2 (pw, dx, dy, nbds, npts, vlist, op, spr, sx, sy)
pw_j>olyline (pw, dx, dy, npts, ptlist, mvlist, brush, tex, op)
pw_polypoint(pw, dx, dy, npts, ptlist, op)
pw_put(pw, x, y, value)
pw_read(pr, dx, dy, dw, dh, op, pw, sx, sy)
pw_region(pw, x, y, width, height)
pw_replrop(pw, dx, dy, dw, dh, op, pr, sx, sy)
pw_reset(pw)
pw_rop(pw, dx, dy, dw, dh, op, sp, sx, sy)
pw_set_region_rect (pw, r, use_same_j?r)
pw_show(pw)
pw__stencil (dpw, dx, dy, dw, dh, op, stpr, stx, sty, spr, sx, sy)
pw_text(pw, x, y, op, font, s)
pw_traprop(pw, dx, dy, t, op, pr, sx, sy)
pw_ttext(pw, x, y, op, font, s)
pw__unlock (pw)
pw_vector(pw, xO, yO, xl, yl, op, value)
pw__write (pw, dx, dy, dw, dh, op, pr, sx, sy)
pw_writebackground(pw, dx, dy, dw, dh, op)_
Pixwin Color Manipulation Functions
pw blackonwhite(pw, min, max) pw_getcolormap(pw, index, count.
pw_cyclecolormap(pw, cycles.
index, count) red, green, blue)
pw_dbl_access (pw)
pw_getdefaultcms (cms, map)
pw__dbl_f lip (pw)
pw_putattributes(pw, planes)
pw dbl_get(pw, attribute)
pw_j?utcolormap (pw, index, count.
pw dbl_release()
red, green, blue)
pw_dbl_set(pw, attributes)
pw reversevideo(pw, min, max)
pw getattributes(pw, planes)
p w_s e t cms n ame (p w, cms name)
pw getcmsname (pw, cmsname)
pw whiteonblack(pw, min, max)
microsystems
Revision A, of May 9, 1988
Chapter 7 — Imaging Facilities: Pixwins 103
7.1. What is a Pixwin? An image in SunView, whether on the screen or in memory, is composed of dots
called pixels and is represented internally as a rectangle of such pixels. The pix-
rect structure is the construct used at a low level to access an image and operate
on it. You can program at the pixrect level to draw on the screen; this is covered
in the Pixrect Reference Manual.
However, in SunView drawing operations are displayed in a window coexisting
on the screen with other, possibly overlapping windows. Except in certain cir¬
cumstances, drawing operations should be “well-behaved,” meaning that they
should not spill over into other windows and they should not be visible in por¬
tions of the window which are covered by other windows. The pixwin is the
interface through which you operate on the pixels in a particular window. It
guarantees that the above two conditions will be met.
Each pixel has a value. On a monochrome display the value is 1 or 0, since the
pixel can only be on or off, black or white. Such pixels are said to be 7 bit deep.
On a color display each pixel can have several values corresponding to different
colors.
This section summarizes the functions provided for accessing the pixels of a
pixwin. Most of the pw_* functions described in this section are based on
corresponding pr_* routines, which are fully documented in the Pixrect Refer¬
ence Manual. For full discussion of the semantics of a given pixwin function,
refer to the discussion of the corresponding pixrect function in the Pixrect Refer¬
ence Manual and/or the errata/addenda section of the most recent Release
Manual.
In particular the pixrect manual gives useful values for the op argument which
determines what the result of combining the source and destination pixels will
be.
The procedures described in this section will maintain the memory pixrect for a
retained pixwin. That is, they perform their operation on the data in memory, as
well as on the screen.
Obtaining the Window’s All of these procedures require the pixwin of the window you are drawing in as
Pixwin an argument. To draw in a canvas, you use the pixwin that is returned by the
procedure:
Pixwin *pw;
canvas_pixwin(canvas);
Canvas canvas;
Look at the example in Section 5.1, Creating and Drawing into a Canvas, to see
how canvas_pixwin () is used.
The pixwin is also available as the value of the CANVAS_PIXWIN attribute of
the canvas subwindow. 39
39 Aside from the canvas pixwin, all windows, regardless of type, have a pixwin which is available as the
value of WIN_P IXWIN. However, most applications should not need to explicitly write pixels into other types
of windows.
7.2. Accessing a Pixwin’s
Pixels
microsystems
Revision A, of May 9, 1988
104 SunView 1 Programmer’s Guide
Write Routines
Basic RasterOp Operations
Other Raster Operations
The following routines allow you to draw areas, backgrounds, vectors, text,
polygons, lines, and polylines in a pixwin.
The following are the basic low-level raster operations that draw on the screen.
They are common to many imaging systems.
pw_write(pw, dx, dy, dw, dh, op, pr, sx, sy)
— or —
pw_rop(pw, dx, dy, dw, dh, op, pr, sx, sy)
Pixwin *pw;
int dx, dy, dw, dh, op, sx, sy;
Pixrect *pr;
pw_wr it e () and pw_rop () are different names for the same procedure.
They perform the indicated rasterop (op) from the source pixrect to the destina¬
tion in the pixwin. Pixels are written to the rectangle defined by dx, dy, dw, and
dh in the pixwin pw using rasterop function op. dx and dy are the position of
the top left-hand comer of the rectangle, and dw and dh are the width and height
of the rectangle. They are copied from the rectangle with its origin at sx, sy in
the source pixrect pointed to by pr.
pw_wr ite () is essential for many window system operations such as scrolling
a window, drawing frames and borders, and drawing an icon on the screen.
The routines in this section are variations on the basic rasterop routine.
pw_writebackground(pw, dx, dy, dw, dh, op)
Pixwin *pw;
int dx, dy, dw, dh, op;
pw_writebackground () uses a conceptually infinite set of pixels, all of
which are set to zero, as the source. It is often used to clear a canvas pixwin
before drawing a new image. 40
The following routine draws a pixel of value at ( x, y) in the addressed
pixwin:
pw_j>ut (pw, x, y, value)
Pixwin *pw;
int x, y, value;
Using this routine to draw is very slow and should be avoided. If you use it, be
sure to read the later sections on batching and locking .
40 Canvases will automatically clear damaged areas if they are set not to be retained, or if the attribute
CANVAS AUTO CLEAR is set. See Chapter 5, Canvases , for more information.
microsystems
Revision A, of May 9, 1988
Chapter 7 — Imaging Facilities: Pixwins 105
There is a similar routine to draw many pixels in a single call,
pw_J5olypoint(pw, dx, dy, npts, ptlist, op)
Pixwin
int
*•
pw;
dx, dy, npts;
struct pr_j50S *ptlist;
int
op;
All npts points in the array ptlist are drawn in the pixwin pw starting at the
offset dx, dy under the control of the op argument.
The next routine draws a vector of pixel value from (xO, yO) to (xl, yl) in the
addressed pixwin using rasterop op:
pw_vector(pw, xO, yO, xl, yl, op, value)
Pixwin *pw;
int xO, yO, xl, yl, op, value;
To replicate a pattern in a pixrect onto a pixwin, use:
pw_replrop(pw, dx, dy, dw, dh, op, pr, sx, sy)
Pixwin *pw;
int dx, dy, dw, dh, op, sx, sy;
Pixrect *pr;
pw__r eplrop () replicates a small “patch” of pattern in a pixrect onto an entire
pixwin. It is often used to draw a patterned background in a window, such as the
root gray pattern in sunview(l). Standard patterns, created by iconedit(l),
may be found in /usr/include/images/square_* .pr.
Text Routines
The following two routines write a string of characters and a single character,
respectively, to a pixwin, using rasterop op as above:
pw_text(pw, x, y, op, font, s)
Pixwin *pw;
int x, y, op;
Pixfont *font;
char *s;
*
pw_char(pw, x, y, op, font, c)
Pixwin *pw;
int x, y, op;
Pixfont *font;
char c;
Revision A, of May 9,1988
106 SunView 1 Programmer’s Guide
These text rendering routines are distinguished by their own coordinate system:
the destination is given as the left edge and baseline of the first character. The
left edge does not take into account any kerning (character position adjustment
depending on its neighbors), so it is possible for a character to have some pixels
to the left of the x-coordinate. The baseline is the y-coordinate of the lowest
pixel of characters without descenders, ‘L’ or ‘o’ for example, so pixels will fre¬
quently occur both above and below the baseline in a string. 41
font may be NULL in which case the system font is used.
The system font is reference counted and shared between software packages.
The following routines are provided to open and close the system font: 42
Pixfont *
pw_pfsysopen()
pw_pfsysclose()
The following routine:
ttext(pw.
x.
y, op.
Pixwin
*pw;
int
x.
y, op;
Pixfont
*font;
char
*s;
Batching and Stenciling
Routines
is just like pw_t ext () except that it writes transparent text. Transparent text
writes the shape of the letters without disturbing the background behind it. This
is most useful with color pixwins. Monochrome pixwins can use pw_text ()
and a pex_src I pix.dst op, which is faster.
Applications such as displaying text perform the same operation on a number of
pixrects in a fashion that is amenable to global optimization. The batchrop pro¬
cedure is provided for these situations:
pw_batchrop(pw, dx,
Pixwin
dy, op, items, n)
*pw;
int dx, dy, op, n;
struct pr_prpos items []; 4 ^
Stencil operations are like raster ops except that the source pixrect is written
through a stencil pixrect which functions as a pixel-by-pixel write enable mask.
The indicated raster operation is applied only to destination pixels where the
stencil pixrect stpr is non-zero; other destination pixels remain unchanged.
41 A font to be used in pw text () is required to have the same pc home. y and character height for all
characters in the font.
42 The system font can also be obtained by calling pf_default ().
43 The structure of pr_prpos is given in Appendix C of the Pixrect Reference Manual.
Revision A, of May 9, 1988
Chapter 7 — Imaging Facilities: Pixwins 107
pw_stencil(dpw, dx, dy f dw, dh, op, stpr, stx,
sty, spr, sx, sy)
Pixwin *dpw;
Pixrect *stpr, *spr;
int dx, dy, dw, dh, op, stx, sty, sx, sy;
Drawing Polygons
Drawing Curved Shapes
Drawing Lines
The following macro draws a polygon within a pixwin:
pw_j>olygon_2(pw, dx, dy, nbds, npts, vlist, op, spr, sx, sy)
Pixwin *pw;
int dx, dy, nbds, op, sx, sy;
int npts In¬
struct pr_jpos *vlist;
Pixrect *spr;
You can create a polygon filled with a solid or textured pattern.
pw_traprop () is a pixwin operation analogous to pw_rop (), which
operates on a trapezon rather than a rectangle:
pw_traprop(pw, dx, dy, t, op, pr, sx, sy)
Pixwin *pw;
struct pr__trap t;
Pixrect *pr;
int dx, dy, op, sx, sy;
pw__traprop () writes the source pixrect pr into the destination pixwin pw via
the operation op. The output is clipped to the trapezon t.
The following routine draws a solid or textured line between two points with a
“brush” of a specified width:
pw_line(pw, xO, yO, xl, yl, brush, tex, op)
Pixwin *pw;
int xO, yO, xl, yl, op;
struct pr_brush *brush;
struct pr_texture *tex;
There is a similar routine to draw several noncontiguous line segments between a
set of points:
pwjpolyline(pw, dx,
Pixwin
int
struct pr_pos
u_char
struct pr_brush
struct pr_texture
dy, npts, ptlist, mvlist
*pw;
dx, dy, npts, op;
*ptlist;
*mvlist;
*brush
*tex;
brush.
tex.
op)
Revision A, of May 9,1988
108 SunView 1 Programmer’s Guide
Read and Copy Routines
7.3. Rendering Speed
The following routines use the pixwin as a source of pixels. To get the value of
the pixel at (x, y) in pixwin pw call:
int
pw_get(pw, x, y)
Pixwin *pw;
int x, y;
To read pixels from a pixwin into a pixrect call:
pw_read(pr, dx, dy, dw, dh, op, pw, sx, sy)
Pixwin
*pw;
int
dx, dy, dw, dh, op, sx, sy;
Pixrect
*pr;
This routine reads pixels from pw starting at offset ( sx, sy), using rasterop op.
The pixels are stored in the rectangle with its origin at dx, dy of width dw and
height dh in the pixrect pointed to by pr.
When the destination, as well as the source, is a pixwin, use:
pw_copy(dpw, dx, dy, dw, dh, op, spw, sx, sy)
Pixwin *dpw, *spw;
int dx, dy, dw, dh, op, sx, sy;
dpw and spw must be the same pixwin. Also, only horizontal or vertical copies
are supported.
These read and copy routines fail if they try to read from a portion of a non-
retained pixwin which is hidden, and therefore has no pixels. Therefore it is con¬
sidered advanced usage to call them on a non-retained pixwin; refer to the section
entitled Handling Fixup in the SunView 1 System Programmer’s Guide.
Making correct and judicious use of explicit display locking and/or batching is
important for getting the best display speed possible.
There are two major impediments to you getting the best possible display render¬
ing speed. The first is display locking , which prevents window processes from
interfering with each other in several ways:
□ Raster hardware may require several operations to complete a change to the
display; one process’ use of the hardware should be protected from interfer¬
ence by others during this critical interval.
□ Changes to the arrangement of windows must be prevented while a process
is painting, lest an area be removed from a window as it is being painted.
□ A software cursor that the window process does not control (the kernel is
usually responsible for the cursor) may have to be removed so that it does
not interfere with the window’s image.
Display locking is relatively expensive compared to the time it takes to do simple
display operations. Thus you can reduce your display time by reducing the
number of times that you have to acquire the display lock. The subsection below
titled Locking explains how to do this.
sun
microsystems
Revision A, of May 9, 1988
Chapter 7 — Imaging Facilities: Pixwins 109
Locking
The second major impediment to maximum display speed is the use of retained
pixwins. It is obvious that if you have to write to the screen and to memory for
every display operation that it will take longer than writing to only one place.
Thus, there is a mechanism, called pixwin batching which allows you to write
only to memory and then refresh the screen with a quick raster operation from
memory. The subsection entitled Batching explains how to use batching.
Locking allows a client program to obtain exclusive use of the display. If the
client program does not obtain an explicit lock, the window system will. For
example, if your application is going to draw one hundred lines it can either
explicitly lock the display once, draw the lines, and unlock explicitly, or it can
ignore locking and simply draw the lines. In the latter case, the window system
will perform locking and unlocking around each drawing operation, acquiring
and releasing the lock one hundred times instead of once.
NOTE For efficiency’s sake, application programs should lock explicitly around a body
of screen access operations.
You can acquire a lock by calling the macro:
pw_lock(pw, r)
Pixwin *pw;
Rect *r;
pw is the pixwin to be used for the output; r is the rectangle in the pixwin’s coor¬
dinate system that bounds the area to be affected. See The Rect Structure in
Chapter 4, Using Windows, for an explanation of the Rect structure.
pw_lock () blocks if the lock is unavailable (if, for example, another process
currently has the display locked).
When the cursor is on the surface where drawing occurs, if the pixwin is locked
with pw_lock (), sometimes the region in which the cursor rect resides is not
drawn to. This results in an empty region (16 x 16 pixels) when the cursor is
moved. The image is put to its correct state when it is redisplayed.
Lock operations for a single pixwin may be nested; inner lock operations merely
increment a count of locks outstanding and are thus very lightweight. Their
affected rectangles must lie within the rectangles affected by the original lock.
To decrement the lock count, call:
pw_unlock(pw)
Pixwin *pw;
When the lock count reaches 0, the lock is actually released.
Since locks may be nested, it is possible for a client procedure to find itself, espe¬
cially in error handling, with a lock which may require an indefinite number of
unlocks. To handle this situation cleanly, another routine is provided. The fol¬
lowing macro sets pw’s lock count to 0 and releases its lock:
pw_reset(pw)
Pixwin *pw;
microsystems
Revision A, of May 9, 1988
110 SunView 1 Programmer’s Guide
Batching
Acquisition of a lock has the following effects:
□ If the cursor is in conflict with the affected rectangle, it is removed from the
screen. While the screen is locked, the cursor will not be moved in such a
way as to disrupt any screen accessing.
□ Access to the display is restricted to the process acquiring the lock.
□ Modification of the database that describes the positions of all the windows
on the screen is prevented.
□ The clipping information for the pixwin is validated and, if necessary,
updated.
□ In the case of a non-retained pixwin with only a single rectangle visible, the
internals of the pixwin mechanism can be set up to bypass the pixwin
software by going directly to the pixrect level on subsequent display opera¬
tions.
While it has the screen locked, a process should not:
□ do any significant computation unrelated to displaying its image.
o invoke any system calls, including other I/O, which might cause it to block.
□ invoke any pixwin calls except pw_unlock () and those described in the
previous section. Accessing a Pixwin’s Pixels. In any case, the lock should
not be held longer than about a quarter of a second, even following all these
guidelines.
When a display lock is held for more than two seconds of process virtual time,
the lock is broken. However, the offending process is not notified by signal,
because a process shouldn’t be aborted for this infraction. Instead, a message is
displayed on the console.
Batching allows you to write only to the memory pixrect of a retained pixwin and
then refresh the screen with the memory pixrect’s contents at specific times. If
you do not explicitly batch when using a retained pixwin, the window system
will write to both the display and memory on every display operation.
Considering the same example used for locking above, if your application pro¬
gram has a retained pixwin and is going to draw one hundred lines, it can either
explicitly start a batch, draw the lines, and end the batch explicitly, or it can
ignore batching and simply draw the lines. In the latter case, the window system
will draw the lines two hundred times instead of one hundred times.
NOTE For efficiency’s sake, application programs should batch explicitly around a
body of screen access operations when using a retained pixwin.
sun
microsystems
Revision A, of May 9,1988
Chapter 7 — Imaging Facilities: Pixwins 111
Two macros are provided to control batching:
pw_batch_on (pw)
Pixwin *pw;
pw_batch_off(pw)
Pixwin *pw;
pw_batch_on () starts a batch; pw_batch_off () refreshes the screen with
the portion of the memory pixrect that has changed. While batching, the pixwin
internally maintains a rectangle that describes which pixels in the memory pix¬
rect need to be transferred to the screen at the end of the batch.
NOTE Don’t turn batching on and leave it on, as this causes problems with scrolling.
The recommended use is batch_on () (draw something in window)
batch_off().
While in the middle of batching, your code might reach a point at which you
would like the screen to be updated. The following macro refreshes the screen,
but otherwise doesn’t change the batching mode:
pw_show(pw)
Pixwin *pw;
Unlike locking operations, batch operations for a single pixwin do not nest.
Thus, each batching routine in this section affects the batching mode/status.
These three macros — pw_batch_on (), pw_bat ch_of f () and
pw_show () — all call the routine pw_batch () which actually implements
the batching mechanism. You can call pw_batch() directly to tell the batch¬
ing mechanism to refresh the screen after every n display operations.
pw_batch(pw, kind)
Pixwin *pw;
Pw_batch_type kind;
Because the routine does more than one kind of thing, calling it is a little tricky,
kind is the kind of batching requested. You use the following macro to convert
n,the number of display operations you want to be batched before a refresh, to a
Pw_batch_type:
♦define PW_OP_COUNT(n) ((Pw_batch_type)(n))
So, to have batching and ensure the image on-screen is refreshed after every n
operations, call:
pw_batch(pw, PW_OP_COUNT(n));
Clients with a group of screen updates to do can gain noticeably by doing the
group as a batch. Also, the locking overhead, discussed above, will only be
incurred when the screen is refreshed. An example of such a group is displaying
a screen full of text, or a series of vectors with pre-computed endpoints.
In considering how to do batching, it’s a good idea to be sensitive to how long
the user is staring at a blank screen or an old image, and adjust the rate of screen
Revision A, of May 9, 1988
112 SunView 1 Programmer’s Guide
refresh accordingly.
Locking and Batching There are situations in which batching around locking calls makes sense. Con-
Interaction sider that
□ while batching, locking calls are a no-op;
□ if a pixwin is not retained, batching calls are a no-op.
Thus, if your application has a switch to run retained or not, it makes good sense
to batch around locking calls. If you batch around locking calls then your appli¬
cation gets the benefit of batching if running retained and the benefit of locking if
running non-retained.
Locking around batches, on the other hand, is not very efficient.
7.4. Clipping With Regions You can use pixwins to clip rectangular regions within a window’s own rec¬
tangular area. The region operation creates a new pixwin that refers to an area
within an existing pixwin:
Pixwin *
pw_region(pw, x, y, w, h)
Pixwin *pw;
int x, y, w, h;
pw is the source pixwin; x, y, w and h describe the rectangle to be included in
the new pixwin. The upper left pixel in the returned pixwin is at coordinates
(0,0); this pixel has coordinates ( x, y) in the source pixwin.
If the source pixwin is retained, the new region will be retained as well. How¬
ever, the region refers back to the bits of memory pixrect of the source pixwin
when accessing the image.
To change the size of an existing region, call:
int
pw_set__region_rect (pw, r, use_same_pr)
Pixwin *pw;
Rect *r;
unsigned use_same_pr;
The position and size of the region pw are set to the rect *r; a return value of -1
indicates failure. This is more efficient then destroying the old region and creat¬
ing a new one. The use_same_pr flag should be set to 0 if you want a new
retained pixrect allocated for the region that is the size of the region.
To determine the size of an existing region, call:
int
pw_get_region_rect (pw, r)
Pixwin *pw;
Rect *r;
microsystems
Revision A, of May 9, 1988
Chapter 7 — Imaging Facilities: Pixwins 113
7.5. Color
Introduction to Color
The Colormap
*r is set to the size and position of the region pw.
When finished with a region, you should release it by calling: to:
pw_close(pw)
Pixwin *pw;
This routine frees any dynamic storage associated with the pixwin, including its
retained memory pixrect, if any. If the pixwin has a lock on the screen, it is
released.
NOTE You should close any regions before closing the pixwin containing the regions.
The dicussion which follows is divided into three sections:
□ Introduction to Color, which introduces the concepts of the colormap and
colormap segments,
□ Changing the Colormap, which describes how to change a colormap seg¬
ment, and
□ Using Color, which describes how to make color applications compatible
with monochrome and grayscale screens, and how to perform smooth anima¬
tion by using double buffering.
Just as there must be arbitration between different windows to decide what is
displayed on the screen when several windows overlap, there must likewise be
some process of allocation when several windows want to display different sets
of many colors all at once. To understand how this works you need to know how
color is handled.
The pixels on a color display are not simply on or off; they take many different
values for different colors. On all current Sun color displays 44 each pixel has 8
bits. Such an “8 bit deep” pixel can have any value from 0 to 255. The value in
each pixel helps to determine what color appears in that dot on the screen, but it
is not in a one-to-one correspondence with die color displayed; otherwise Sun
color displays would only be able to display 256 different colors.
Instead, the value of the pixel serves as an index into the colormap of the display.
The colormap is an array of 256 colormap entries. The colormap entry for each
index drives the color that is actually displayed for the corresponding pixel value.
A colormap entry consists of 8 bits of red intensity, 8 bits of green intensity and
8 bits of blue, packaged into the following structure:
struct singlecolor {
u_char red, green, blue;
};
Hence a Sun color display is capable of displaying over 16 million colors
(because each colormap entry has 24 bits) but can only display 256 colors simul¬
taneously (because there are only 256 colormap entries).
44 See cgone(4S), cgtwo(4S) and cgfour(4S) in the UNIX Interface Overview manual.
microsystems
Revision A, of May 9, 1988
114 SunView 1 Programmer’s Guide
A Colormap Example
Changing the Colormap
Colormap Segments
Suppose that in a group of pixels on the screen, some have the value 0 while oth¬
ers have the value 193. All pixels with the same value will be displayed in the
same color. The colormap determines what that color will be. If entry 0 in the
colormap of the screen is
red = 250; green =0; blue =3;
then the pixels with a value of 0 will come out bright red. If entry 0 in the color-
map is changed to
red = 1; green = 8; blue = 2;
then the pixels with a value of 0 will immediately change color to an almost-
black green. Similarly, entry 193 in the colormap determines what color the pix¬
els with a value of 193 will have.
Because changing the colormap is much faster than redrawing many thousands of
pixels with a new value, manipulating the colormap is the basis of many graphics
and animation techniques. For examples of programs that manipulate the color-
map, run /usr/demo/suncube or /usr/demo/flight.
Try running spheresedemo -g plus another color program at the same time.
You will notice that as you move the mouse into the spheresdemo window,
the colors in the other windows on the display change dramatically. This is
because hardware is only capable of displaying 256 colors at once. When two
programs that each want to display 256 different colors are run simultaneously,
the window system itself must manipulate the colormap. When the cursor enters
one of the windows, the window system changes the colormap to use the colors
of that window.
The window system allows each window to claim a portion of the total available
colormap entries, called a colormap segment. The colormap segment need not be
the same in all windows of a tool: frames and subwindows can have different
colormaps, or can share colormaps (see Sharing Colormap Segments below). If
the total number of entries in all the colormap segments being requested exceeds
the limit of 256 at any given time, the window system gives priority to the win¬
dow under the cursor, and removes segments belonging to other windows as
necessary.
The window system loads colormap segments at arbitrary locations within the
colormap. To the application program, this indirection is transparent. The rou¬
tines that access a pixwin’s pixels do not distinguish between windows which use
colormap segments and those which use the entire colormap.
NOTE While you can have multiple pixwins within a window, there is only one color-
map segment per window. A separate colormap for each pixwin in a window is
not supported. This limitation should only be of interest if you are using pixwin
regions (described in the SunView System Programmer’s Guide).
sun
microsystems
Revision A, of May 9, 1988
Chapter 7 — Imaging Facilities: Pixwins 115
Background and Foreground
Default Colormap Segment
Changing Colors from the
Command Line
Sharing Colormap Segments
Every colormap segment has two distinguished values, its background and fore¬
ground. The background color is defined as the value at the first position of a
colormap segment; the foreground color is the value at the last position.
The first pixwin created for a window sets the background and foreground of the
window to be those of the default colormap segment. This is the monochrome
colormap segment defined in
<sunwindow/cms_mono. h>. Subsequent pixwins created for the window
inherit the background and foreground of the window.
The user can modify the default colormap for all applications by invoking -
sunview with the -F and -B command line arguments. 45 The user can also
change the default colormap segment on a per-application basis by invoking the
application with certain flags. The -Wf flag sets the foreground color, -Wb sets
the background color, and -Wg specifies that the colormap of the frame will be
inherited by the frame’s subwindows.
The equivalent frame attributes for these flags are
FRAME_FOREGROUND_COLOR, FRAME_BACKGROUND_COLOR, and
FRAME__INHERIT_COLORS.
It is possible for different processes to share a single colormap segment. For
some applications, you want to guarantee that your colormap segment is not
shared by another process. For example, a colormap segment to be used for ani¬
mation, as described later in the section on Double Buffering, should not be
shared. The way to ensure that a colormap segment will not be shared by another
window is to give it a unique name. A common way to generate a unique name
is to append the process’ id to a more meaningful string that describes the usage
of the colormap segment.
If a colormap segment’s usage is static in nature, then it pays to use a shared
colormap segment definition, since colormap entries are scarce. Windows, in the
same or different processes, can share the same colormap by referring to it by the
same name.
There are three basic types of shared colormap segments:
□ A colormap segment used by a single program. Sharing occurs when multi¬
ple instances of the same program are running. An example of such a pro¬
gram is a color terminal emulator in which the terminal has a fixed selection
of colors.
□ A colormap segment used by a group of highly interrelated programs. Shar¬
ing occurs whenever two or more programs of this group are running at the
same time. An example of such a group is a series of CAD/CAM programs
in which it is common to have multiple programs running at the same time.
45 This is not true fora Sun-3/110 and other machines with cgfour frame buffers, due to their use of an
overlay plane to implement most monochrome windows.
Background and Foreground
Default Colormap Segment
Changing Colors from the
Command Line
Sharing Colormap Segments
Revision A, of May 9,1988
116 SunView 1 Programmer’s Guide
Example: showcolor
□ A coloimap segment used by a group of unrelated programs. Sharing occurs
whenever two or more programs of this group are running. An example of
such a colormap segment is the default coloimap, cms_monochrome,
defined in <sunwindow/ cms_mono. h>. Other common useful color-
map segment definitions that you can use and share with other windows
include cms_rgb. h, cms_grays. h, cms_mono. h, and
cms rainbow. h, found in <sunwindow/cms_* . h>.
The program on the following page shows the actual colors in the display’s
colormap. It should help you see how the window system manages the color-
map. Run this program soon after bringing up sunview, then run several color
graphics programs such as the demos mentioned earlier. Try bringing up dif¬
ferent windows with different foreground and background colors, as in:
/*
* showcolor.c
* Draw a grey ramp that graphically shows the colormap
* segment activity of the environment when the cursor
* is NOT in the canvas of this tool.
*/
♦include <suntool/sunview.h>
♦include <suntool/canvas.h>
♦define CMS_SIZE 256
♦define CAN HEIGHT 10
main(argc, argv)
char **argv;
{
Frame
Canvas
register Pixwin
register int
u char
frame;
canvas;
*pw;
i;
red[CMS_SIZE],
green[CMS_SIZE],
blue[CMS_SIZE];
/* Create frame and canvas */
frame = window_create(0, FRAME,
FRAME_LABEL, a rgv[0],
FRAME_ARGS, argc, argv,
0 );
canvas = window_create (frame, CANVAS,
WIN__HEIGHT, CAN_HEIGHT,
WIN_WIDTH, 2 * CMS_SIZE,
0 );
window_fit (frame) ;
pw = canvas ^pixwin(canvas);
/* Initialize colormap to grey ramp */
(?)
sun
microsystems
Revision A, of May 9, 1988
Chapter 7 — Imaging Facilities: Pixwins 117
for (i = 0; i < CMS_SIZE; i++)
red[i] = green[i] = blue[i] = i;
pw_setcmsname (pw, "showedor") ;
pw_putcolormap(pw, 0, CMS_SIZE, red, green, blue);
/* Draw ramp of colors */
for (i = 0; i < CMS_SIZE; i++)
pw_rop(pw, i*2, 0, 2, CAN_HEIGHT,
PIX_SRC | PIX_C0L0R(i), (Pixrect *)0, 0, 0);
window_main_loop (frame) ;
exit(0);
Manipulating the Colormap
The following sections document the routines that implement the techniques
described above.
To change a window’s colormap segment, you must:
1. Name the colormap segment with pw setcmsname ().
2. Set the size of the segment by loading the colors with
pw_putcolormap().
It is important that these two steps happen in order and together. The call to
pw_setcmsname () does not take effect until you write at least one color
value into the colormap with pw_putcolormap ().
You set and retrieve the name of a colormap segment with these two functions:
pw_setcmsname(pw, name)
Pixwin *pw;
char name[CMS_NAMESIZE];
pw_getcmsname(pw, name)
Pixwin *pw;
char name[CMS_NAMESIZE];
If you set the foreground and back¬
ground colors (which are entries
count -1 and 0 in the colormap
segment, respectively) to the same
color, the system will change them
to the foreground and background
colors of sunview. In other words,
you are prevented from making the
foreground and background colors
of a pixwin indistinguishable.
Setting the name resets the colormap segment to a NULL entry. After calling
pw_setcmsname (), you must immediately call pw_j?ut colormap () to set
the size of the colormap segment and load it with the actual colors desired.
pw_j?ut colormap () and the corresponding routine to retrieve the colormap’s
state, pw_getcolormap (), are defined as follows:
microsystems
Revision A, of May 9,1988
118 SunView 1 Programmer’s Guide
Cycling the Colormap
Miscellaneous Utilities
pw_putcolormap(pw, index,
Pixwin *pw;
int index,
unsigned char red[].
count, red, green, blue)
count;
green[], blue[];
pw_getcolormap(pw, index, count, red, green, blue)
Pixwin *pw;
int index, count;
unsigned char red[ ], green[ ], blue[ ];
pw_put colormap loads the count elements of the pixwin’s colormap seg¬
ment starting at index (zero origin) with the first count values in the three
arrays.
The first time pw_put colormap () is called after calling
pw_set cmsname (), the count parameter defines the size of the colormap
segment. The size of a colormap segment must be a power of 2, and can’t be
changed unless pw set cmsname () is called with another name. You can call
pw_put colormap () subsequently to modify a subrange of the colormap —
use a larger value for index and a smaller value for count.
NOTE If you attempt to install a colormap segment that is not a power of 2, your color-
map segment has a high likelyhood of taking up too much space. This means
that the screen will flash when you move the cursor into the window with this
odd sized colormap.
In Appendix A, Example Programs, there is a program called coloredit which
uses pw_putcolormap () to change the colors of its subwindows as the user
adjusts sliders for red, green and blue.
A utility is provided to make it easy to cycle colormap entries:
pw_cyclecolormap(pw, cycles, index, count)
Pixwin *pw;
int cycles, index, count;
Starting at index, the count entries of the colormap associated with the
pixwin’s window are rotated among themselves for cycles. A cycle is defined
as number of shifts it takes one entry to move through every position once.
To see an example of colormap cycling, run jumpdemo (6) with the -c option.
If you are are going to cycle one of the common colormap segment definitions,
you should give the colormap a unique name, otherwise the colormap of other
applications will change as well.
The following utilities are provided as convenient ways to set the forground and
background colors to common settings, min should be the first entry in the
colormap segment, representing the background color, max should be the last
entry, representing the forground color.
microsystems
Revision A, of May 9, 1988
Chapter 7 — Imaging Facilities: Pixwins 119
Using Color
Cursors and Menus
pw_reversevideo(pw, min, max)
Pixwin *pw;
int min, max;
pw__blackonwhite (pw, min, max)
Pixwin *pw;
int min, max;
pw_whiteonblack(pw, min, max)
Pixwin *pw;
int min, max;
On a monochrome display, these calls don’t take effect until you write to the
pixwin. On a color display, they take effect immediately.
This section gives some notes on the use of color by cursors and menus, how to
make color applications compatible with monochrome and grayscale screens, and
how to use double buffering for smooth animation.
Cursors appear in the foreground color, the last color in the pixwin’s colormap.
Menus and prompts use fullscreen access, covered in Chapter 12, Menus and
Prompts, of the SunView 1 System Programmer’s Guide. Fullscreen access saves
the colors in the first and last entries of the screen’s colormap, puts in the fore¬
ground and background colors, and displays the menu or prompt. This means
that depending on where your application’s colormap segment resides in the
screen’s colormap, some colors in your tool may change whenever menus or
prompts are put up. You can allow for this by making the background and fore¬
ground colors in your colormap segment the same as the screen’s background
and foreground.
There are other menu/cursor “glitches” that occur when running applications on
frame buffers which support multiple plane groups. These are covered in the
later section on Multiple Plane Groups.
Is My Application Running on a None of the colormap manipulations described in this chapter causes an error if
Color Display? run on a monochrome display. All colors other than zero map to the foreground
color, so if your application displays colored objects on a background of zero,
they will appear as black objects on a white foreground on a monochrome
display 46 . The window system detects and prevents the foreground and back¬
ground being the same color on color displays.
However, you may may want to determine at run time whether your application
has a color or monochrome display available to it. For example, when displaying
a chart, you may want to use patterns if colors are not available. You can deter¬
mine whether the display is color or monochrome by finding out how deep the
pixels are. Each pixwin includes a pointer to a pixrect which represents its pixels
on the screen. Pixrects, in turn, have a depth field which holds the number of bits
44 Unless you are running with Mack and white inverted, using the -i option to sunview.
Revision A, of May 9, 1988
120 SunView 1 Programmer’s Guide
per screen pixel. Thus
c -
A
Pixwin *pw;
int depth = pw->pw_jpixrect->pr_depth;
s._______
_>
will have a value of 1 for windows displayed on monochrome devices, and a
value greater than 1 for color screens. Currently, all Sun color displays have 8
bits per pixel.
Simulating Grayscale on a There is no way to tell if your application is running on a grayscale monitor.
Color Display since it runs off the same color board. The grayscale monitor is usually driven
from the red output of the color board, so if two colors have different green and
blue values but the same red value, they will show up the same on a greyscale
display.
To see how your color application will look on a grayscale monitor, temporarily
set your colormap segment so that the green and blue components of each color-
map entry are the same as the red component. This will simulate the grayscale
display on a color monitor.
Software Double Buffering Sometimes you want to rapidly display different images in an application. If you
just use the pixwin write operations to display the new image, the redrawing of
the pixels will be perceptible to the user, even though the operations are fast.
Instead, you can use a technique called software double-buffering.
As we have seen, on a color display, there are 8 bits associated with each pixel.
If you are not using 256 shades at once, then some of these bits are unused.
What you would like to do is to store values for two or more different images in
these 8 bits, but only display one set of values at a time.
The first goal can easily be accomplished using the pw_j>utattributes ()
routine to restrict writes to a particular set of planes:
pw_j?utattributes (pw, planes)
Pixwin *pw;
int *planes;
planes is a bitplane access enable mask. Only those bits of the pixel
corresponding to a 1 in the same bit position of *planes will be affected by
pixwin operations. If planes is NULL, that attribute value will not be written.
A corresponding routine is provided to retrieve the value of the access enable
mask:
pw_getattributes(pw, planes)
Pixwin *pw;
int *planes;
NOTE Use pw_putattributes () with care, as it changes the internal state of the
pixwin.~ The correct usage is to first save the existing bitplane mask by calling
microsystems
Revision A, of May 9, 1988
Chapter 7 — Imaging Facilities: Pixwins 121
pw_get at tributes (), then call pw_j>ut attributes (), then, when
done, restore the initial state by calling pw_put at tributes () with the saved
mask.
The second goal — only displaying what is in some of the planes — is trickier.
There is no way to tell the hardware to only look at the values in some of the
planes to determine the colors to show.
What you do instead is modify the colormap so that only values in certain planes
of the colormap change the color on the display, so in effect only those planes are
visible. For example, to display two different four-color images you could use
the colormap shown in the following table.
Table 7-1 Sample Colormap to Isolate Planes
Pixel Value
Colormap A
(Only upper planes
are “visible")
Colormap B
(Only lower planes
are “visible”
0 0 0 0
blue
blue
0 0 0 1
blue
red
0 0 10
blue
green
0 0 11
blue
pink
0 10 0
red
blue
0 10 1
red
red
0 110
red
green
0 111
red
pink
10 0 0
green
blue
10 0 1
green
red
10 10
green
green
10 11
green
pink
110 0
pink
blue
110 1
pink
red
1110
pink
green
1111
pink
pink
From the above table, you can see that if colormap A is set (using
pw_put colormap () ), then no matter what the value in the two lower planes,
the color displayed is the same; the value in the upper two planes alone controls
the color. So, if you use this colormap while only enabling the two lower planes
(by passing pw^put at tributes () the value 3 ), then the values you write
into the lower planes won’t change what is shown.
When you switch to colormap B, the situation is reversed. Only the values in the
lower planes affect what is visible. You would then pass
pw_putattributes () the value 12 to write to the upper two planes. The
two sets of colors need not be the same, so you can switch between two
different-colored images.
xr microsystems
Revision A, of May 9, 1988
122 SunView 1 Programmer’s Guide
Using Software Double
Buffering For Smooth
Animation
Hardware Double-Buffering
You would use the same technique to switch between more images and/or to
display more colors. You can display two different images, each with 16 dif¬
ferent colors, or 8 different monochrome images, or values in between.
One application of the above technique is to provide smooth animation. To
move an image across the screen, you must draw it in one location, erase it, and
redraw it in another. Even on a fast system, the erasing and redrawing is visible.
You’d like the object to immediately appear in its new position, without disap¬
pearing momentarily. You can do this by alternating two colormaps so that the
object disappears in its old location and reappears in a new one. This is called
software double-buffering, because you are using the display planes as alternat¬
ing buffers; as you write to one set of planes, the other set of planes is displayed.
The colormaps in the table on the preceding page come from the software pro¬
gram animatecolor in Appendix A, Example Programs. This program uses
software double buffering to animate some squares. The routines it uses to create
the two colormaps and swap between them are complicated, but can be reused in
more sophisticated graphics applications.
The following routines will allow programs to do true hardware double-buffering
on the Thecg5board. on the device driver interface, refer the the cgtwo(4S)
manual page. 47 color framebuffer and on future framebuffers that support
double-buffering.
Double-buffering is treated as an even scarcer resource than colormaps, since
only one window can be truly double-buffered at any one time. The cursor con¬
trols which window will flip the display buffers. Applications are able to run the
same code on non-double-buffered displays and it will be as if the double¬
buffering calls were never made. The following code fragment contains proto¬
typical application code.
--
Rect rectangle;
Pixwin *pw;
rectangle.r_left= ... ;
if (!pw_dbl_get (pw, PW_DBL_AVAIL))
{ ... if program cares ... }
pw_dbl_access (pw); *
while (rendering__frames) {
... calculate one frame ...
pw_lock (pw, &rectangle);
... render one frame ...
... may include unlocks and locks ...
pw__dbl_flip (pw);
pw_unlock (pw);
}
pw_dbl_release (pw);
s___ )
47 The cg5 board is binary compilable with both the Sun-3 Color Board and the Sun-2 Color Board. cg5 is
necessary for hardware double-buffering.
microsystems
Revision A, of May 9, 1988
Chapter 7 — Imaging Facilities: Pixwins 123
The notion of the “active” double-buffering window is important. There is at
most one active window at a time. If the cursor is in a double-buffering window,
then the window is the active double-buffering window. If the cursor leaves the
active window, that window remains active until the cursor enters another
double-buffering window. If the active double-buffering window dies, goes
iconic, or becomes totally obscured, and the cursor is not left in a double¬
buffering window, then the top-most visible double-buffering window becomes
the active window (if there is one).
Only the active window will be allowed to write to a single buffer. All other win¬
dows write to both buffers, so that when the display flips to the other buffer, their
contents remain unchanged. The notion of active will change only during a
pw_dbl_f lip () call.
pw_dbl_access() which resets the window’s data structure so that first frame
will be rendered to the background. The very first double buffer sets both READ
and WRITE to the backgound. pw_dbl_access() should only be called when
ready to actively animate:
pw_dbl_access (pw)
Pixwin *pw;
If the pixwin’s window has not been accessed for double-buffering then there is
no change, and both buffers will be written to.
If the window is marked as accessible for double-buffering and the window is
“active”, then the frame double-buffering control to whatever this window
requested with its last pw_dbl_set () call. If there was no pw_dbl_set ()
call, then set write and READ to the background. Change the frame buffer
double-buffering control bits to reflect this.
If the window is accessible for double-buffering then potentially flip the display.
The display is flipped only if the window is “active” : pw_dbl_f lip () deter¬
mines if its window has become active:
pw_dbl_flip(pw)
Pixwin *pw;
The flip can be done inside or outside of a lock region although it may be prefer¬
able to place inside a lock region just before an unlock so that calculations for the
next frame can proceed even if another window momentarily grabs the lock. The
flip from one buffer to another is synchronized with the display’s vertical retrace.
The procedure
pw_dbl_release(pw)
Pixwin *pw;
signifies the end of double-buffering by the window associated with the pixwin.
Call pw_dbl_release () as soon as your program has completed a section of
active animation. This procedure will copy the foreground buffer to the back¬
ground. Because of this, it is important to leave the animation loop after a
pw_dbl_f lip () has been done and before drawing the next frame has started.
Otherwise, the window will contain an incomplete buffer image after the release.
Revision A, of May 9,1988
124 SunView 1 Programmer’s Guide
SunView provides the ability for an actively double-buffering window to write to
both buffers. For example, the instrument gauge readings can be set in a real¬
time simulator. If pw is not the active double buffer, the frame buffer control bits
are not changed. The procedure and the attributes that it may use are discussed
below.
pw_dbl_set(pw, attributes)
Pixwin *pw;
<attribute-Iist> attributes;
Table 7-2 Pixwin-Level set Attributes
Attribute
Possible Values to set
PW_DBL_WRITE
PW DBL READ
PW_DBL_FORE, PW_DBL_BACK, PW_DBL_BOTH
PW DBL FORE, PW_DBL_BACK_
The attribute value returned from pw_dbl_get () does not reflect the true state
of double buffering hardware. This is especially true if the active double buffer
is not this pixwin. The procedure and the attributes that is uses are given below.
pw_dbl_get(pw, attribute)
Pixwin *pw;
Pw dbl attribute attribute;
Table 7-3 Pixwin-Level get Attributes
Attribute
Possible Values Returned
PW_DBL_AVAIL
PW_DBL_DISP LAY
PW_DBL_EXISTS
PW_DBL_WRITE
PW_DBL_FORE, PW_DBL_BACK, PW_DBL_BOTH
PW DBL READ
PW DBL FORE, PW DBL BACK
7.6. Plane Groups and the
cgfour Frame Buffer
The Sun-3/110, Sun-3/60, and Sun-4/110 color machines use the
cgfour (4s) 48 frame buffer, which supports multiple “plane groups.” Each
displays either 24-bit color or black and white. In the former case its color is
determined by a value in an 8-bit color buffer, in the latter case, a monochrome
buffer called the overlay plane.
Whether the pixel displays in color or black/white is controlled by the value for
the pixel in the enable plane, a third plane. If the value in the enable plane is not
set, then the 8-bit deep value in the color buffer is passed to the circuitry that pro¬
duces the color from the lookup table. If it is set, then the overlay plane deter¬
mines the pixel’s color (black or white). The effect is like having a color and
monochrome display in one, with the enable plane determining which is shown
in each pixel.
48 Read the cgfour (4s) manual page for more information on this frame buffer architecture.
Xr microsystems
Revision A, of May 9, 1988
Chapter 7 — Imaging Facilities: Pixwins 125
In fact, in the color Sun-3/60 and Sun-4/110 plane group implementations, you
can set the colors in the overlay plane to other that black and white. There are
only two colors in the overlay plane since it is only one-bit deep, but they can
have colors other than black and white assigned to them.
Such sets of buffers are referred to as plane groups.
SunView and Plane Groups At the pixrect level it is possible to manipulate the three plane groups of multiple
plane group framebuffers directly. At the SunView level, some decisions have
been made for you. Raster operations in the overlay plane are faster than in the
color plane, so SunView objects which only use the foreground and background
colors such as frames, text subwindows, panels, cursors, menus, etc. all try to ran
in the overlay plane. If you set the foreground and background explicitly using
the techniques explained in Changing Colors from the Command Line above, or
if you have told sunview to run in the color buffer only by giving it the com¬
mand line argument -8bit_color_only, then these objects will run in the
color plane.
However, canvases and graphics subwindows default to using the color plane
group whenever possible, on the assumption that you want to draw in color. If
this is not the case, then you may find that your application runs faster if you hint
to these subwindows to use the overlay plane:
□ For canvases, set the attribute CANVAS_FAST_MONO, either when creating
the canvas or later, as in:
window_set(canvas, CANVAS_FAST_MONO, TRUE, 0) ;
If your application uses scrollbars, then you need to set
CANVAS_FAST_MONO before you create the canvas’ scrollbars, since they
share the canvas’ pixwin.
□ For graphics subwindows in old-style Sun Windows applications, use the
pixwin call pw_use_f ast_monochrome (pw) as follows:
' ----- \
pw_use_fast_monochrome (gfx->gfx_jpixwin) ;
---,
Both calls affect only multiple plane group displays, so it is safe and desirable to
put them in any Sun application that uses monochrome canvases or graphics
subwindows. Again, if the user gives the appropriate command line arguments,
canvases and graphics subwindows will ran in the color plane regardless of these
calls.
microsystems
Revision A, of May 9, 1988
126 SunView 1 Programmer’s Guide
“Glitches” Visible when Using
Plane Groups
sunview and Plane Groups
For performance reasons, the cursor image is only written in the plane group of
the window under it. So, if the cursor’s hot spot is in a black and white window
in the overlay plane and there is an adjacent color window, that part of its image
that would lie over the color window is invisible, since it is drawn in the overlay
plane but the enable plane is still showing the value in the color buffer. The
same disappearance applies in the reverse situation.
When menus are drawn, the enable plane is set so that they are visible.
It is possible to direct sunview(l) to only use the color buffer or the overlay
plane; it is also possible to start up a second copy of sunview in the other plane
group, and switch between them using swit cher(l) or -
ad jacent screens(l). Consult these programs’ manual pages for more infor¬
mation.
#sun
XT microsystems
Revision A, of May 9, 1988
Text Subwindows
Text Subwindows
129
Summary Tables.
8.1. Text Subwindow Concepts.
Creating a Subwindow.
Attribute Order.
Determining a Character’s Position.
Getting a Text Selection.
Editing a Text Sub window.
8.2. Loading a File.
Checking the Status of the Text Subwindow
Textsw_status Value.
8.3. Writing to a Text Subwindow.
Insertion Point.
Positioning to End of Text.
8.4. Reading from a Text Sub window.
8.5. Editing the Contents of a Text Subwindow.
Removing Characters.
Emulating an Editing Character.
Replacing Characters.
The Editing Log.
Which File is Being Edited?.
Interactions with the File System.
8.6. Saving Edits in a Subwindow.
129
132
132
132
132
132
132
133
133
133
134
135
135
135
136
136
136
137
138
138
138
139
Storing Edits. 139
Discarding Edits. 139
8.7. Setting the Contents of a Text Sub window. 140
TEXTSW_FILE_CONTENTS . 140
TEXTSW_CONTENTS . 140
TEXTSW_INSERT_FROM_FILE . 141
8.8. Positioning the Text Displayed in a Text Subwindow. 141
Screen Lines and File Lines. 141
Absolute Positioning. 142
Relative Positioning. 142
How Many Screen Lines are in the Subwindow?. 143
Which File Lines are Visible?.;.... 143
Guaranteeing What is Visible. 143
Ensuring that the Insertion Point is Visible. 143
8.9. Finding and Matching a Pattern. 144
Matching a Span of Characters. 144
Matching a Specific Pattern. 144
8.10. Marking Positions. 145
8.11. Setting the Primary Selection. 147
8.12. Dealing with Multiple Views. 147
8.13. Notifications from a Text Subwindow. 148
Summary Tables
Text Sub windows
This chapter describes the text subwindow package, which you can use by
including the file <suntool/textsw. h>.
Figure 8-1 is a text subwindow. A text subwindow allows a user or client to
display and edit a sequence of ASCII characters. These characters are stored in a
file or in primary memory. Its features range from inserting into a file to search¬
ing for and replacing a string of text or a character.
Figure 8-1 Text Subwindow
textedit - (NONE), dir: /usr/topaz/yvonne
To give you a feeling for what you can do with text subwindows, overleaf there
is a list of the available text subwindow attributes and functions. Many of these
are discussed in the rest of this chapter and elsewhere (use the Index to check).
All are briefly described with their arguments in the text subwindow summary
tables in Chapter 19, SunView Interface Summary:
□ the Text Subwindow Attributes table begins on page 366;
□ the Text sw_act ion Attributes table begins on page 370;
□ the Textsw_status Values table begins on page 371;
□ the Text Subwindow Functions table begins on page 372.
129
Revision A, of May 9, 1988
130 SunView 1 Programmer’s Guide
Text Subwindow Attributes
TEXTSW ADJUST IS PENDING DELETE
TEXTSW_INSERT_FROM_FILE
TEXTSW AGAIN_RECORDING
TEXTSW_INSERT_MAKES_VISIBLE
TEXTSW AUTO INDENT
TEXTSW_INSERTION_POINT
TEXTSW_AUTO_SCROLL_BY
TEXTSW_LEFT_MARGIN
TEXTSW BLINK_CARET
TEXTSW_LENGTH
TEXTSW_BROWSING
TEXTSW_LINE_BREAK_ACTION
TEXTSW_CHECKPOINT_FREQUENCY
TEXTSW_LOWER_CONTEXT
TEXT SW_CLIENT_DATA
TEXT SW_MEMORY_MAXIMUM
TEXT SW_CONFIRM_OVERWRITE
TEXTSW_MENU
TEXTSW_CONTENTS
TEXTSW_MODIFIED
TEXT SW_CONTROL_CHARS_U SE_F ONT
TEXTSW_MULTI_CLICK_SPACE
TEXT SW_DISABLE_CD
TEXTSW_MULTI_CLICK_TIMEOUT
TEXTSW_DISABLE_LOAD
TEXTSW_NOTIFY_PROC
TEXTSW_EDIT_COUNT
TEXT SW_READ_ONLY
TEXTSW_FILE
TEXTSW_SCROLLBAR
TEXTSW_FILE_CONTENTS
TEXTSW_STATUS
TEXTSW_FIRST
TEXTSW_STORE_CHANGES_FILE
TEXTSW_FIRST_LINE
TEXTSW_STORE_SELF_IS_SAVE
TEXTSW_HISTORY_LIMIT
TEXTSW_UPDATE_SCROLLBAR
TEXTSW_IGNORE_LIMIT
TEXTSW_UPPER_CONTEXT
Textsw
action Attributes
TEXT SW_ACTION_CAPS_LOCK
TEXTSW_ACTION_TOOL_CLOSE
TEXT SW_ACTION_CHANGED_DIRECTORY
TEXTSW_ACTION_TOOL_DESTROY
TEXT SW_ACTION_EDITED_FILE
TEXT SW_ACTION_TOOL_QUIT
TEXTSW_ACTION_EDITED_MEMORY
TEXTSW_ACTION_TOOL_MGR
TEXT SW_ACTION_FILE_IS_READONLY
TEXTSW_ACTION_USING_MEMORY
TEXTSW_ACTION_LOADED_FILE
®siin
Xr microsystems
Revision A, of May 9,1988
Chapter 8 — Text Subwindows 131
microsystems
Revision A, of May 9,1988
132 SunView 1 Programmer’s Guide
8.1. Text Subwindow
Concepts
Creating a Subwindow
Attribute Order
Determining a Character’s
Position
Getting a Text Selection
Editing a Text Subwindow
This section introduces the basic concepts of a text subwindow.
You create a text subwindow the same way that you create any SunView window
object, by calling the window creation routine with the appropriate type parame¬
ter:
Textsw textsw;
textsw = window create (base_frame, TEXTSW, attributes, 0) ,
The attributes in the above call constitute an attribute list which is discussed in a
Section later in this chapter, titled Attribute-based Functions.
Most attributes are orthogonal; thus you usually need not worry about their order.
However, in a few cases the attributes in a list may interact, so you need to be
careful to specify them in a particular order. Such cases are noted in the sections
which follow. 49 In particular, you must pass TEXTSW_STATUS first in any call
to window_create () or window_set () if you want to find the status after
setting some other attribute in the same call.
The contents of a text subwindow are a sequence of characters. At any moment,
each character can be uniquely identified by its position in the sequence (type
Textsw_index). Editing operations, such as inserting and deleting text, cause
the index of any particular character to change over time. The valid indices are 0
through length-1 inclusive, where length is the number of characters currently in
the text subwindow, returned by the TEXTSW_LENGTH attribute.
The text subwindow has a notion of the current index after which the next char¬
acter will be inserted at any given moment. This is called the insertion point. A
caret is drawn on the screen immediately after this index to give the user a visual
indication of the insertion point.
A text selection is made by the user, and it is indicated on the screen with
reverse-video highlighting. A text subwindow function or procedure is not used
to determine which window has the current selection or to retrieve information
contained in a text subwindow. Instead, these functions are earned out by the
Selection Service. For an example of how this is done, refer to Section 16, The
Selection Service.
A text subwindow may be edited by the user, or by a client program. When you
create a text subwindow, by default the user can edit it. By using the special
attributes discussed in this section, the client program can edit the subwindow.
These edits are then stored in /tmp/textProcess-id.Counter.
The following five sections explain the functions and attributes that you will use
to load, read, write, edit, and finally save a text file.
49 For a discussion of attribute ordering in general, see Section 4.8, Attribute Ordering.
#sun
microsystems
Revision A, of May 9,1988
Chapter 8 — Text Subwindows 133
8.2. Loading a File
You can load a file into a textsw by using TEXTSW FILE, as in:
f “ >
window_set (textsw, TEXTSW_FILE, file__name, 0) ;
v-—___>
Keep in mind, that if the existing text has been edited, then these edits will be
lost. To avoid such loss, first check whether there are any outstanding edits by
calling:
- -- ..
window_get(textsw, TEXTSW_MODIFIED)
---,
The above call to window_set () will load the new file with the text posi¬
tioned so that the first character displayed has the same index as the first charac¬
ter that was displayed in the previous file — which is probably not what you
want. To load the file with the first displayed character having its index specified
by position, use the following:
- — ->.
window_set(textsw, TEXTSW_FILE, file_name,
TEXTSW_FIRST, position, 0);
___y
NOTE The order of these attributes is important. Because attributes are evaluated in
the order given, reversing the order would first reposition the existing file, then
load the new file. This would cause an unnecessary repaint, and mis-position the
old file, if it was shorter than posit ion. For a full discussion of attribute ord¬
ering, see Section 8.5.
Checking the Status of the Both of the above calls blindly trust that the load of the new file was successful.
Text Subwindow This is, in general, a bad idea. To find out whether the load succeeded, and if
not, why not, use the following call:
-
window_set(textsw,
TEXTSW_STATUS, Sstatus,
TEXTSW_FILE, file_name,
TEXTSW_FIRST, position,
0 ) ;
k_/
where status is declared to be of type Textsw_status.
NOTE The TEXTSW_STATUS attribute and handle must appear in the attribute list
before the operation whose status you want to determine.
Text sw_status Value The valid values for such a variable are enumerated in the following table, where
the common prefix TEXTSW_STATUS_ has been removed. For example, OKAY
in the table is actually TEXTSW_STATUS_OKAY.
microsystems
Revision A, of May 9, 1988
134 SunView 1 Programmer’s Guide
Table 8-1 Textsw_status Values
Value _ Description _
The operation encountered no problems.
The attribute list contained an illegal or unrecognized attribute.
TEXT SW_S TATU S_OKAY
TEXT SW_S TATU S_BAD_AT TR
TEXT SW_S TATU S_BAD_AT TR_VALUE
TEXTSW_STATUS_CANNOT_ALLOCATE
TEXT S W_S TATU S_C ANN OT__OP EN_I NP UT
TEXT S W_S TAT U S_C ANN OT_I N SERT_FROM__F ILE
TEXTSW_STATUSJ3UT_0F_MEM0RY
TEXTSW STATUS OTHER ERROR
The attribute list contained an illegal value for an attribute,
usually an out of range value for an enumeration.
A call to calloc(2) or malloc(2) failed.
The specified input file does not exist or cannot be accessed.
The operation encountered a problem when trying
to insert from file.
The operation ran out of memory while editing in memory.
The operation encountered a problem not covered by any of
the other error indications.
8.3. Writing to a Text
Subwindow
To insert text into a text subwindow at the current insertion point, call:
Textsw_index
textsw_insert(textsw, buf, buf_len)
Textsw textsw;
char *buf;
int buf_len;
The return value is the number of characters actually inserted into the text
subwindow. This number will equal buf_len unless either the text subwindow
has had a memory allocation failure, or the portion of text containing the inser¬
tion point is read only. The insertion point is moved forward by the number of
characters inserted.
NOTE This routine does not do terminal-style interpretation of the input characters.
Thus “editing” characters (such as CTRL-H or DEL for character erase, etc.) are
simply inserted into the text subwindow rather than performing edits to the exist¬
ing contents of the text subwindow. In order to do terminal-style emulation, you
must pre-scan the characters to be inserted, and invoke textsw_edit () where
appropriate, as described in the next section.
#sun
\T microsystems
Revision A, of May 9,1988
Chapter 8 — Text Subwindows 135
Insertion Point The attribute TEXTSW_INSERTI0N_P0INT is used to interrogate and to set
the insertion point. For instance, the following call determines where the inser-
tion point is:
Textsw_index point;
point = (Textsw_index)window_get(textsw,
TEXTSW_INSERTION_POINT) ;
L-_
_
A
whereas the following call sets the insertion point to be just before the third char¬
acter of the text:
window_set (textsw, TEXTSW_INSERTION_POINT, 2, 0);
<_
\
Positioning to End of Text To set the insertion point at the end of the text, set
textsw_insertion_point to the special index TEXTSW__INFINITY.
NOTE This call does not ensure that the new insertion point will be visible in the text
subwindow, even if the TEXTSW_INSERT_MAKES_VISIBLE attribute is
TRUE. To guarantee that the caret will be visible afterwards, you should call
textsw_j?ossibly_normalize ().
8.4. Reading from a Text Many applications that incorporate text subwindows never need to read the con-
Subwindow tents of the text directly from the text subwindow. Often, this is because the text
subwindow is only being used to display text to the user.
Even when the user is allowed to edit the text, some applications simply wait for
the user to perform some action that indicates that all of the edits have been
made. They then use either textsw_save () or textsw_store_f ile () to
place the text in the file. The text can then be read via the usual file input utili¬
ties, or the file itself can be passed off to another program.
It is, however, useful to be able to directly examine the text in the text subwin¬
dow. You can do this using the TEXTSW_CONTENTS attribute. The following
code fragment illustrates how to use TEXTSW_CONTENTS to get a span of char¬
acters from the text subwindow. It gets the 1000 characters beginning at position
500 out of the text subwindow and places them into a null-terminated string.
f -—--N
♦define TO_READ 1000
char buf[TO_READ+l];
Textsw_index next_pos;
next_j?os = (Textsw_index)
window_get(textsw, TEXTSW_CONTENTS, 500, buf, TO_READ) ;
if (next_jpos != 500+TO_READ) {
Error case
} else
buf[TO_READ] = '\0';
v___>
microsystems
Revision A, of May 9,1988
136 SunView 1 Programmer’s Guide
8.5. Editing the Contents of The file or memory being edited by a text subwindow is referred to as the back-
a Text Subwindow ing store. Several attributes and functions are provided to allow you to manipu¬
late the backing store of a text subwindow. 50 This section describes the pro¬
cedures and attributes that you can use to edit a text subwindow.
Removing Characters You can remove a contiguous span of characters from a text subwindow by cal¬
ling:
Textsw_index
textsw__delete (textsw, first, last_j?lus_one)
Textsw textsw;
Textsw_index first, last_plus_one;
first specifies the first character of the span that will be deleted, while
last_plus_one specifies the first character after the span that will not be
deleted, first should be less than, or equal to, last_plus_one. To delete
to the end of the text, pass the special value TEXTSW_INFINITY for
last_j?lus_one.
The return value is the number of characters deleted, and is last_plus_one
- first, unless all or part of the specified span is read-only. In this case, only
those characters that are not read-only will be deleted, and the return value will
indicate how many such characters there were. If the insertion point is in the
span being deleted, it will be left at first.
A side-effect of calling textsw_delete () is that the deleted characters
become the contents of the global Clipboard. To remove the characters from the
textsw subwindow without affecting the Clipboard, call:
Textsw_index
textsw_erase(textsw, first, last_plus_one)
Textsw textsw;
Textsw_index first, last_j?lus_one;
Again, the return value is the number of characters removed, and
last_plus_one can be TEXTSW_INFINITY.
Both of these procedures will return 0 if the operation fails.
Emulating an Editing You can emulate the behavior of an editing character, such as CTRL-H, with
Character textsw_edit ():
Text s w__index
textsw_edit(textsw, unit, count, direction)
Textsw textsw;
unsigned unit, count, direction;
50 Note that the edit log maintained by the text subwindow package is reset on each operation affecting the
backing store. For a description of the edit log, see the discussion at the end of Editing the Contents of a Text
Subwindow.
microsystems
Revision A, of May 9, 1988
Chapter 8 — Text Subwindows 137
Replacing Characters
Depending on the value of unit, this routine will erase either a character, a
word, or a line. Set unit to:
□ TEXTSW_UNIT_IS_CHAR to erase individual characters,
□ TEXTSW_UNIT_IS_W0RD to erase the span of characters that make up a
word (including any intervening white space or other non-word characters),
or
□ textsw_unit_is_line to erase all characters in the line on one side of
the insertion point.
If the direction parameter is 0, the operation will affect characters after the
insertion point, otherwise it will affect characters before the insertion point
The number of times the operation will be applied is determined by the value of
the count parameter. Set it to one to do the edit once, or to a value greater than
one to do multiple edits in a single call. textsw_edit () returns the number
of characters actually removed.
For example, suppose you want to interpret the function key ITT) as meaning
“delete word forward”. On receiving the event code for the (FT) key going up,
you would make the call:
--- \
textsw_edit(textsw, TEXTSW_UNIT_IS_WORD, 1, 0);
- ---- ,
While a span of characters may be replaced by calling text sw_erase () fol¬
lowed by textsw_insert ( ), character replacement is done most efficiently
by calling:
Text sw_index
textsw_replace_bytes(textsw, first, last_plus_one, buf, buf_len)
Textsw textsw;
Textsw_index first, last_plus_one;
char *buf;
int buf_len;
The span of characters to be replaced is specified by first and
last_jplus_one, just as in the call to text sw_erase (). The new charac¬
ters are specified by buf and buf_len, just as in the call to
textsw_insert (). Once again, if last_plus_one is
TEXTSw_infinity, the replace affects all characters from first to the end
of the text. If the insertion point is in the span being replaced, it will be left at
first + buf_len.
The return value is the net number of bytes inserted. The number is negative if
the original string is longer than the one which replaces it. If a problem occurs
when an attempt is made to replace a span, then it will return an error code of 0.
textsw_replace_bytes (), like text sw_erase () , does not put the
characters it removes on the global Clipboard.
microsystems
Revision A, of May 9, 1988
138 SunView 1 Programmer’s Guide
The Editing Log All text subwindows allow the user to undo editing actions. In order to imple¬
ment this feature, the text subwindow package keeps a running log of all the
edits. If there is a file associated with the text subwindow, this log is kept in a
file in the /tmp directory.
This file can grow until this directory runs out of space. To limit the size of the
edit log and to avoid filling up all of tmp the user can set the tex wrap around
size in the default sedit(l) Tty/text_wraparound_size . If there is no associ¬
ated file, the edit log is kept in memory, and the maximum size of the log is con¬
trolled by the attribute TEXTSW_MEMORY_MAXIMUM, which defaults to 20,000
bytes.
Unfortunately, once an edit log kept in memory has reached its maximum size,
no more characters can be inserted into or removed from the text subwindow. In
particular, since deletions, as well as insertions, are logged, space cannot be
recovered by deleting characters.
It is important to understand how the edit log works because you may want to use
a text subwindow with no associated file to implement a temporary scratch area
or error message log. If such a text subwindow is used for a long time, the
default limit of 20,000 bytes may well be reached, and it will be impossible for
either the user or your code to insert any more characters even though there may
be only a few characters visible in the text subwindow. Therefore, it is recom¬
mended to set TEXT SW_MEMORY_MAX IMUM much higher, say to 200,000.
Which File is Being Edited? To find out which file the text subwindow is editing, call:
int
textsw_append_f ile__name (textsw, name)
Textsw textsw;
char *name;
If the text subwindow is editing memory, then this routine will return a non-zero
value. Otherwise, it will return 0, and append the name of the file to the end of
name.
If a text subwindow is editing a file called my file and the user chooses ‘Save
Current File’ from the subwindow’s menu (or client code invokes
textsw_save ()), the following sequence of file operations occurs:
a myfile is copied to myfile%
□ The contents of my f i 1 e % are combined with information from the edit log
file (/tmp /Text Process-id. Counter) and written over myfile (thereby
preserving all its permissions, etc).
□ The edit log file is removed from /tmp.
If myfile is a symbolic link to .Jsome_dir/ otherf ile, then the backup file
is created as ../some dir/ otherf ile%.
Interactions with the File
System
Revision A, of May 9,1988
Chapter 8 — Text Sub windows 139
8.6. Saving Edits in a
Subwindow
Storing Edits
Discarding Edits
Keep in mind that the user can change the current directory by selecting ‘Load
File’ or ‘Set Directory’ from the text subwindow menu. If my file is a relative
path name, then the copy to myf ile% and the save take place in the current
directory.
To save any edits made to a file currently loaded into a text subwindow call:
unsigned
textsw_save(textsw, locx, locy)
Textsw textsw;
int locx, locy;
locx and locy are relative to the upper left comer of the text subwindow and
are used to position the upper left comer of the alert should the save fail for some
reason — usually they should be 0. The return value is 0 if and only if the save
succeeded.
The text subwindow may not contain a file, or the client may wish to place the
edited version of the text (whether or not the original text came from a file) in
some specific file. To store the contents of a text subwindow to a file call:
unsigned
textsw_store_file(textsw, filename, locx, locy)
Textsw textsw;
char *filename;
int locx, locy;
Again, locx and locy are used to position the upper left comer of the message
box. The return value is 0 if and only if the store succeeded.
NOTE By default, this call changes the file that the text subwindow is editing, so that
subsequent saves will save the edits to the new file. To override this policy, set
the attribute TEXTSW_STORE_CHANGES_FILE to FALSE.
To discard the edits performed on the contents of a text subwindow, call:
void
textsw_reset(textsw, locx, locy)
Textsw textsw;
int locx, locy;
locx and locy are as above. Note that if the text subwindow contains a file
which has not been edited, the effect of textsw reset is to unload the file
and replace it by memory provided by the text subwindow package; thus the user
will see an absolutely empty text subwindow. Alternatively, if the text subwin¬
dow already was editing memory then another, untouched, piece of primary
memory will be provided and the edited piece will be deallocated.
The rest of this chapter describes the other functions that are available for text
subwindows. These features include setting the contents of a subwindow, setting
the primary selection, and how to deal with multiple or split views.
microsystems
Revision A, of May 9,1988
140 SunView 1 Programmer’s Guide
8.7. Setting the Contents of You may want to set the initial contents of a text subwindow that your applica-
a Text Subwindow tion uses. For example, the SunView mailtool sets the initial contents of the
composition window to come up with the headings To, Subject, and so on.
To set the initial contents of a text subwindow, use one of three attributes:
TEXTSW_INSERT_FROM_FILE, TEXTSW_FILE_CONTENTS, and
TEXTSW__CONTENTS. Each attribute is illustrated in code fragments given
below.
TEXTSW_FILE_CONTENTS The attribute TEXTSW_FILE_C0NTENTS makes it possible for a client to ini¬
tialize the text subwindow contents from a file yet still edit the contents in
memory. The user can return a text subwindow to its initial state after an editing
session by choosing ‘Undo All Edits’ in the text menu.
The following code fragment shows how you would use this attribute.
Textsw textsw;
char *filename;
Textsw_index pos;
window_set(textsw,
TEXTSW_FILE_CONTENTS, filename,
TEXTSW_FIRST, pos,
0 );
When the client calls the undo routine and filename is not a null string, then it
will initialize the memory used by the text subwindow with the contents of the
file specified by filename.
When the client calls the undo routine and the filename is a null string, then it
will initialize the memory used by the text subwindow with the previous contents
of the text subwindow.
TEXTSW CONTENTS TEXTSW_CONTENTS lets you insert a text string from memory, instead of a file,
into the text subwindow. The default for this attribute is NULL.
If you use window_create () with this attribute, then it will specify the initial
contents for a non-file text subwindow.
If you use window_set () with this attribute it will set the contents of a win¬
dow as in:
If you use window_get () with this attribute, then you will need to provide
additional parameters as in:
The return value is the next position to be read. The buffer array
Revision A, of May 9, 1988
Chapter 8 — Text Subwindows 141
buf [0.. .buf_len-l ] is filled with the characters from textsw beginning at
the index pos, and is null-terminated only if there were too few characters to fill
the buffer.
TEXTSW_lNSERT_FROM_FiLE textsw_insert_FROM_file allows a client to insert the contents of a file
into a text subwindow at the current insertion point. It is the progr amm ing
equivalent of a user choosing ‘Include File’ from the text menu.
The following code fragment is a sample of using this attribute.
8.8. Positioning the Text
Displayed in a Text
Subwindow
Screen Lines and File Lines
Three status values may be returned for this attribute when the argument
TEXTSW_STATUS is passed in the same call to window_create () or
window_set ():
□ TEXTSW_STATUS_OKAY — the operation was successful.
□ TEXTSW_STATUS_CANNOT_INSERT_FROM_FILE — the operation
failed
□ TEXTSW_STATUS_OUT_OF_MEMORY —the function cannot insert the
text, because it ran out of memory
Usually there is more text managed by the text subwindow than can be displayed
all at once. As a result, it is often necessary to determine the indices of the char¬
acters that are being displayed, and to control exactly which portion of the text is
being displayed.
When there are long lines in the text it is necessary to draw a distinction between
two different definitions of “line of text.”
A screen line reflects what is actually displayed on the screen. A line begins
with the leftmost character in the subwindow and continues across until either a
newline character or the right edge of the subwindow is encountered. A file line,
on the other hand, can only be terminated by the newline character. It is defined
as the span of characters starting after a newline character (or the beginning of
the file) running through the next newline character (or the end of the file).
Whenever the right edge of the subwindow is encountered before the newline, if
TEXTSW_LINE_BREAK_ACTION is TEXTSW_WRAP_AT_CHAR, the next
character and its successors will be displayed on the next lower screen line. In
this case there would be two screen lines, but only one file line. From the per¬
spective of the display there are two lines; from the perspective of the file only
one. If, on the other hand TEXTSW_LINE_BREAK_ACTI0N is
TEXTS W_WRAP_AT_W0RD, the entire word will be displayed on the next line.
microsystems
Revision A, of May 9, 1988
142 SunView 1 Programmer’s Guide
Absolute Positioning
Relative Positioning
Unless otherwise specified, all text subwindow attributes and procedures use the
file line definition.
NOTE Line indices have a zero-origin, like the character indices; that is, the first line
has index 0, not 1.
Two attributes are provided to allow you to specify which portion of the text is
displayed in the text subwindow.
Setting the attribute TEXTSW_FIRST to a given index causes the first character
of the line containing the index to become the first character displayed in the text
subwindow. Thus the following call causes the text to be positioned so that the
first displayed character is the first character of the line which contains index
1000. This call only positions one view at a time:
--
window_set(textsw, TEXTSW_FIRST, 1000, 0);
L _____
\
To position all of the views in a text subwindow, use the attribute
TEXTSW FOR ALL VIEWS as in the following call:
—
window_set(textsw,TEXTSW_FOR_ALL_VIEWS, TRUE,
TEXTSW_FIRST, 1000, 0);
Conversely, the following call retrieves the index of the first displayed character:
c
index * (Textsw index)window_get(textsw, TEXTSW_FIRST);
v---—-
A related attribute, useful in similar situations, is TEXTSW_FIRST_LINE.
When used in a call on window_set () or window_get (), the value is a
file line index within the text.
You can determine the character index that corresponds to a given line index
(both zero-origin) within the text by calling:
Textsw_index
textsw_index_for_file_line(textsw, line)
Textsw textsw;
int line;
The return value is the character index for the first character in the line, so char¬
acter index 0 always corresponds to line index 0.
To move the text in a text subwindow up or down by a small number of lines,
call the routine:
void
textsw_scroll_lines(textsw, count)
Textsw textsw;
int count;
A positive value for count causes the text to scroll up, just as if the user had
used the left mouse button in the scrollbar, while a negative value causes the text
Revision A, of May 9, 1988
Chapter 8 — Text Subwindows 143
to scroll down, as if the user had used the right mouse button in the scrollbar.
How Many Screen Lines are When calling text sw_scroll_lines () you may want to know how many
in the Subwindow? screen lines are in the text subwindow. You can find this out by calling:
int
textsw_screen_line_count(textsw)
Textsw textsw;
Which File Lines are Visible? Exactly which file lines are visible on the screen is determined by calling:
void
textsw_file_lines_visible(textsw, top, bottom)
Textsw textsw;
int *top, *bottom;
This routine fills in the addressed integers with the file line indices of the first and
last file lines being displayed in the specified text subwindow.
Guaranteeing What is Visible To ensure that a particular line or character is visible, call:
void
textsw_j?ossibly_normalize(textsw, position)
Textsw textsw;
Textsw_index position;
The text subwindow must be displayed on the screen, before this function will
work.
If the character at the specified position is already visible, then this routine
does nothing. If it is not visible, then it repositions the text so that it is visible
and at the top of the subwindow.
If a particular character should always be at the top of the subwindow, then cal¬
ling the following routine is more appropriate:
void
textsw_normalize_view(textsw, position)
Textsw textsw;
Textsw_index position;
Ensuring that the Insertion Point
is Visible
Most of the programmatic editing actions do not update the text subwindow to
display the caret, even if textsw_insert_makes_visible is set If you
want to ensure that the insertion point is visible, call something like
-——--
textsw_possibly_normalize(textsw,
(Textsw_index) window_get(textsw, TEXTSW_INSERTION_POINT) ;
V___,
microsystems
Revision A, of May 9, 1988
144 SunView 1 Programmer’s Guide
8.9. Finding and Matching A common operation performed on text is finding a span of characters that match
a Pattern some specification. The text subwindow provides several rudimentary pattern
matching facilities. This section describes two functions that you may call in
order to perform similar operations.
To find the nearest span of characters that match a pattern, call:
int
textsw_find_bytes(textsw, first, last_plus_one, buf,
buf_len, flags)
Textsw textsw;
Textsw_index *first, *last_plus_one;
char *buf;
unsigned buf_len;
unsigned flags;
The pattern to match is specified by buf and buf_len. The matcher looks for
an exact and literal match — it is sensitive to case, and does not recognize any
kind of meta-character in the pattern, first specifies the position at which to
start the search. If flags is 0, the search proceeds forwards through the text, if
1 the search proceeds backwards. The return value is -1 if the pattern cannot be
found, else it is some non-negative value, in which case the indices addressed by
first and last_plus_one will have been updated to indicate the span of
characters that match the pattern.
Matching a Specific Pattern Another useful operation is to find delimited text. For example, you might want
to find the starting brace and the ending brace in a piece of code. To find a
matching pattern, call:
int
textsw__match_bytes(textsw, first, last_plus_one,
start_sym, start__sym_len,
end_sym, end_sym_len, field_flag)
Textsw
Textsw_index
char
int
unsigned
first stores the starting position of the pattern that you want to search for.
last_plus_one stores the cursor position of the end pattern. Its value is one
position past the text. start_sym and end_sym store the beginning position
and ending position of the pattern respectively. start_sym_len and
end_sym_len store starting and ending pattern’s length respectively.
Use one of the three field flag values to search for matches:
TEXTSW_DELIMITER_FORWARD, TEXTSW_DELIMITER_BACKWARD, and
TEXTSW~DELIMITER_ENCLOSE.
□ TEXTSW_DELIMITER_FORWARD begins from first and searches for¬
ward until it finds start_sym and matches it forward with end_sym.
textsw;
♦first, *last_plus_one;
*start_sym, *end_sym;
start_sym_len, end_sym_len;
field_flag;
Matching a Span of
Characters
Revision A, of May 9,1988
Chapter 8 — Text Sub windows 145
8.10. Marking Positions
□ TEXTSW_delimiter_backward begins from first and searches
backward for end_sym and matches it backward with start_sym .
□ TEXTSW_DELIMITER_ENCL0SE begins from first and expands both
directions to match start_sym and end_sym of the next level.
If no match is found, then text sw_match_bytes () will return a value of
-1. If a match is found, then it will return the index of the first match.
The following code fragment is an example of finding delimited text. Notice that
the field_f lag value is TEXTSW_DELIMITER FORWARD.
Textsw__index first, last_plus_one f pos;
first* (Textsw_index) window__get(textsw, TEXTSW_INSERTION_POINT) ;
pos = textsw_match_bytes(textsw, Sfirst, &last_j>lus_one,
strlen( M */ M ),
strlen("*/"), TEXTSW_DELIMITER_FORWARD) ;
if (pos > 0) {
textsw_set__selection(textsw, first, last_plus_one, 1) ;
window_set(textsw, TEXTSW_INSERTION_POINT, last_plus_one, 0) ;
} else
(void) window__bell(textsw);
^ - ---- >
This code searches forward from first until it finds the starting */ and
matches it forward with the next */. If no match is found, a bell will ring in the
text subwindow.
Often a client wants to keep track of a particular character, or group of characters
that are in the text subwindow. Given that arbitrary editing can occur in a text
subwindow, and that it is very tedious to intercept and track all of the editing
operations applied to a text subwindow, it is often easier to simply place one or
more marks at various positions in the text subwindow. These marks are
automatically updated by the text subwindow to account for user and client edits.
There is no limit to the number of marks you can add.
A new mark is created by calling:
Textsw_mark
textsw_add_mark(textsw, position, flags)
Textsw textsw;
Textsw__index position;
unsigned flags;
The flags argument is either TEXTSW_MARK_DEF AULTS or
T EXT S W_MARK_MOVE_AT_I NS ERT . The latter causes an insertion that occurs
at the marked position to move the mark to the end of the inserted text, whereas
the former causes the mark to not move when text is inserted at the mark’s
current position. As an example, suppose that the text managed by the text
subwindow consists of the two lines
microsystems
Revision A, of May 9,1988
Assume a marie is set at position 5 Oust before the i in is on the first line) with
flags Of TEXTSW_MARK_MOVE_AT_INSERT.
When the user selects just before the is (thereby placing the insertion point before
the i, at position 5) and types an Bh, making the text read
the marie moves with the insertion point and they both end up at position 6.
However, if the flags had been TEXT SW_MARK_DEFAULT S , then the marie
would remain at position 5 after the user typed the h, although the insertion point
moved on to position 6.
Now, suppose instead that the user had selected before the this on the first line,
and typed Kep, making the text read
In this case, no matter what flags the mark had been created with, it would end
up at position 8, still just before the i in is.
If a mark is in the middle of a span of characters that is subsequently deleted, the
mark moves to the beginning of the span. Going back to the original scenario,
with the original text and the mark set at position 5, assume that the user deletes
from the h in this through the e in the on the first line, resulting in the text
When the user is done, the marie will be at position 1, just before the e in te.
The current position of a marie is determined by calling:
Text sw_index
textsw_find_mark(textsw, mark)
Textsw textsw;
Textsw_mark mark;
An existing mark is removed by calling:
void
textsw_remove_mark(textsw, mark)
Textsw textsw;
Textsw_mark mark;
Note that marks are dynamically allocated, and it is the client’s responsibility to
keep track of them and to remove them when they are no longer needed.
microsystems
Revision A, of May 9,1988
Chapter 8 — Text Subwindows 147
8.11. Setting the Primary The primary selection may be set by calling:
Selection
void
textsw_set_selection(textsw, first, last_plus_one, type)
Textsw textsw;
Textsw_index first, last_plus_one;
unsigned type;
A value of 1 for type means primary selection, while a value of 2 means secon¬
dary selection, and a value of 17 is pending delete Note that there is no require¬
ment that all or part of the selection be visible; use
textsw_possibly_normalize () (described previously in Section 8.5,
Editing the Contents of a Text Subwindow) to guarantee visibility.
8.12. Dealing with Multiple By using the ‘Split View’ menu operation, the user can create multiple views of
Views the text being managed by the text subwindow. Although these additional views
are usually transparent to the client code controlling the text subwindow, it may
occasionally be necessary for a client to deal directly with all of the views. This
is accomplished by using the following routines, and the information that split
views are simply extra text subwindows that happen to share the text of the origi¬
nal text subwindow.
Textsw
textsw_first(textsw)
Textsw textsw;
Given an arbitrary view out of a set of multiple views, text sw_f irst ()
returns the first view (currently, this is the original text subwindow that the client
created). To move through the other views of the set, call:
Textsw
textsw__next (textsw)
Textsw textsw;
Given any view of the set, text sw_next () returns some other member of the
set, or NULL if there are none left to enumerate. The following loop is
guaranteed to process all of the views in the set:
for (textsw=textsw_first(any_split);
*textsw;
textsw=textsw_next(textsw)) {
processing involving textsw;
1
When you create a text subwindow take into account that your user may split the
window. If you do something like try to enlarge the window, you will run into
problems.
microsystems
Revision A, of May 9,1988
148 SunView 1 Programmer’s Guide
8.13. Notifications from a The text subwindow notifies its client about interesting changes in the
Text Subwindow subwindow’s or text’s state by calling a notification procedure. It also calls this
procedure in response to user actions. If the client does not provide an explicit
notification procedure by using the attribute TEXTSW_NOTIFY_PROC, then the
text subwindow provides a default procedure. The declaration for this procedure
looks like:
void
notify_proc(textsw, avlist)
Textsw textsw;
Attr_avlist avlist;
avlist contains attributes that are the members of the Text sw_action
enumeration.
Your notification procedure must be careful to either process all of the possible
attributes that it can be called with or to pass through the attributes that it does
not process to the standard notification procedure. This is important because
among the attributes that can be in the avlist are those that cause the standard
notification procedure to implement the Front, Back, Open, Close, and Quit
accelerators of the user interface.
Here is an example of a client notify procedure, and a code fragment demonstrat¬
ing how it would be used:
m sun
NT microsystems
Revision A, of May 9, 1988
Chapter 8 — Text Subwindows 149
default_textsw_notify =
(void (*)())window_get(textsw, TEXTSW_NOTIFY_PROC);
window_set(textsw, TEXTSW_NOTIFY_PROC, client_notify_proc);
The Text sw_act ion attributes which may be passed to your notify procedure
are listed in the following table (duplicated in Chapter 19, SunView Interface
Summary ). Remember that they constitute a special class of attributes which are
passed to your textsw notification procedure. They are not attributes of the text
subwindow in the usual sense, and can not be retrieved or modified using
window_get () or window_set ().
Table 8-2 Textsw action Attributes
Attribute
Value Type
Description
TEXT SW_ACTION_CAP S LOCK
boolean
The user pressed the CAPS-lock function key to change the
setting of the CAPS-lock (it is initially 0, meaning off).
TEXTSW_ACTION_CHANGED_DIRECTORY
char *
The current working directory for the process has been
changed to the directory named by the provided string value.
TEXTSW_ACTION_EDITED FILE
char *
The file named by the provided string value has been edited.
Appears once per session of edits (see below).
TEXTSW_ACTION_EDITED MEMORY
none
monitors whether an empty text subwindow has been edited.
TEXTSW_ACTION_FILE IS READONLY
char *
The file named by the provided string value does not have
write permission.
TEXTSW_ACTION_LOADED_FILE
char *
The text subwindow is being used to view the file named
by the provided string value.
TEXTSW_ACTION_TOOL CLOSE
(no value)
The frame containing the text subwindow should become
iconic.
TEXTSW_ACTION_TOOL_DESTROY
Event *
The tool containing the text subwindow should exit,
without checking for a veto from other subwindows.
The value is the user action that caused the destroy.
TEXT SW_ACTION_TOOL_QUIT
Event *
The tool containing the text subwindow should exit
normally. The value is the user action that caused
the exit.
TEXTSW_ACTION_TOOL MGR
Event *
The tool containing the text subwindow should do the
window manager operation associated with the
provided event value.
TEXTSW_ACTION_USING_MEMORY
(no value)
The text subwindow is being used to edit a string stored in
primary memory, not a file.
microsystems
Revision A, of May 9, 1988
150 SunView 1 Programmer’s Guide
The attribute TEXTSW_ACTI0N_EDITED_FILE is a slight misnomer, as it is
given to the notify procedure after the first edit to any text, whether or not it
came from a file. This notification only happens once per session of edits, where
notification of TEXTSW_ACTlON_LOADED_FILE is considered to terminate
the old session and start a new one.
NOTE The attribute TEXTSW_ACTlON_LOADED_F ILE must be treated very care¬
fully. This is because the notify procedure gets called with this attribute in
several situations: after a file is initially loaded, after any successful ‘Save
Current File’ menu operation, after a 'Undo All Edits’ menu operation, and dur¬
ing successful calls to textsw_reset (), textsw_save () and
textsw_store().
The appropriate response by the procedure is to interpret these notifications as
being equivalent to:
“The text subwindow is displaying the file named by the provided
string value; no edits have been performed on the file yet. In addition,
any previously displayed or edited file has been either reset, saved, or
stored under another name.”
Revision A, of May 9,1988
Panels
Panels . 153
9.1. Introduction to Panels and Panel Items. 158
Message Items. 15 g
Button Items . 15 g
Choice Items. 15 g
Toggle Items. 1 59
Text Items . 15 9
Slider Items. 15 9
9.2. Basic Panel Routines. 159
Creating and Sizing Panels. 159
Creating and Positioning Panel Items. 160
Explicit Item Positioning. 160
Default Item Positioning. 1 6 1
Laying Out Components Within an Item. 162
Modifying Attributes. 162
Panel-Wide Item Attributes. I 63
Retrieving Attributes . I 63
Destroying Panel Items. I 64
9.3. Using Scrollbars With Panels. 165
Creating Scrollbars . I 65
Scrolling Panels Which Change Size. 165
Detaching Scrollbars from Panels. 1 66
9.4. Messages. I 67
9.5. Buttons. 167
Button Selection. 167
Button Notification. 167
Button Image Creation Utility. 168
9.6. Choices... 170
Displaying Choice Items. 170
Choice Selection. 172
Choice Notification. 172
Choice Value. 172
Choice Menus. 172
9.7. Toggles. 176
Displaying Toggles. 176
Toggle Selection. 176
Toggle Notification... 176
Toggle Value. 176
Toggle Menus. 178
9.8. Text. 178
Displaying Text Items. 178
Text Selection. 179
Text Notification. 180
Writing Your Own Notify Procedure. 181
Text Value. 182
Text Menus. 183
9.9. Sliders. 184
Displaying Sliders. 184
Slider Selection. 184
Slider Notification. .'. . 184
Slider Value. 185
9.10. Painting Panels and Individual Items. 185
9.11. Iterating Over a Panel’s Items. 188
9.12. Panel Item Client Data. 188
9.13. Event Handling . 189
Default Event Handling. 189
Writing Your Own Event Handler. 189
Translating Events from Panel to Window Space. 193
Panels
Quick Reference, Listings and
Summary Tables
This chapter describes the panel subwindow package, which you can use by
including the file <suntool/panel, h>.
Section 1 provides a non-technical introduction to panels. Section 2 introduces
the basic concepts and routines needed to use panels. Scrollable panels are
covered in Section 3. Sections 4 through 9 describe the different types of panel
items in detail, including examples.
For examples of complete panels, see the programs filer, imagebrowser 1 and
image browser_2, which are listed in Appendix A and discussed in Chapter 4,
Using Windows.
For quick reference, the next two pages are a visual index to the different effects
possible in panels. After that come lists of the available panel and panel item
attributes, functions and macros. Many of these are discussed in the rest of this
chapter and elsewhere (use the Index to check). Finally, tables that summarize
the usage of panel attributes, functions and macros are in Chapter 19, SunView
Interface Summary:
□ the Panel Attributes table begins on page 346;
□ the Generic Panel Item Attributes table begins on page 347;
o the Choice and Toggle Item Attributes table begins on page 349;
□ the Slider Attributes table begins on page 351;
□ the Text Item Attributes table begins on page 352;
□ the Panel Functions and Macros table begins on page 353.
microsystems
153
Revision A, of May 9,1988
154 SunView 1 Programmer’s Guide
Page Description
167 Messages
168 Buttons
173 Choice (default)
173 Choice (custom marks)
173 Choice (inverted)
174 Choice (current)
174 Choice (cycle)
175 Choice (dial)
175 Choice (images, menu)
171 Choice (images)
Example
This action will cause unsaved edits to be lost.
[Reset] [ Reset ]
Drawing Mode: 0 Points a Line 0 Rectangle 0 Circle 0 Text
Drawing Mode: Points ►Line Rectangle Circle Text
Drawing Mode: Points IWHH Rectangle Circle Text
Drawing Mode: Line
Drawing Mode: v Line
Rect
Line
Points
Circle
Text
Drawing Mode
v
1 ■
Points
Line
□
Rectangle
Circle
o
Text
abc
D S f
■ ■ ■
microsystems
Revision A, of May 9, 1988
Chapter 9 — Panels 155
Page Description
177 Toggle (vertical)
178 Text
179 Text (masked)
Example
Format Options:
O' Long
□ Reverse
B'shou all files
Name: Eduard G. Robinson
Passuord: A*******
183 Text with menu
File: dervish.Inage
ESC - Filename completion b
- Load Inage fron file
A S - Store Image to file
A B - Browse directory
A Q - Quit
185 Slider
Brightness: [75]
188
168 Button with menu
Sun
View
Introduction
SunVIeu Model
Windows
Canvases
Input
Manual
Plxwlns
Text Subulndous
Panels
TTY Subulndows
Menus
Cursors
Icons
Scrollbars
Selection Service
Notlfler
]
194 Buttons with menus
on scrollable panel
microsystems
Revision A, of May 9, 1988
156 SunView 1 Programmer’s Guide
Panel Attributes
PANEL_ACCEPT_KEYSTROKE
PANEL EVENT PROC PANEL LABEL BOLD
PANE L_BACKGROUND_PROC
PANEL FIRST_ITEM PANEL_LAYOUT
PANEL_BLINK_CARET
PANEL ITEM_X_GAP PANEL_SHOW_MENU
PANEL CARET ITEM
PANEL ITEM Y GAP
Generic Panel Item Attributes
PANEL ACCEPT_KEYSTROKE
PANEL MENU CHOICE IMAGES
PANEL_CLIENT_DATA
PANEL_MENU_CHOICE_STRINGS
PANEL_EVENT_PROC
PANEL MENU_CHOICE_VALUES
PANEL_ITEM_RECT
PANEL_MENU_TITLE_FONT
PANE L_ITEM_X
PANEL_MENU_TITLE_IMAGE
PANEL_ITEM_Y
PANEL_MENU_TITLE_STRING
PANEL_LABEL_X
PANEL_NEXT_ITEM
PANEL_LABEL_Y
PANEL_NOTIFY_PROC
PANEL_LABEL_BOLD
PANEL_PAINT
PANEL_LABEL_FONT
PANEL_PARENT_PANEL
PANE L_LABEL_IMAGE
PANEL_SHOW_ITEM
PANEL_LABEL_STRING
PANEL_SHOW_MENU
PANEL_LAYOUT
PANEL_VALUE_X
PANEL MENU CHOICE FONTS
PANEL VALUE_Y
Choice and Toggle Item Attributes
PANEL_CHOICE_FONTS
PANEL MARK IMAGE
PANEL_CHOICE_IMAGE
PANEL_MARK_IMAGES
PANEL_CHOICE_IMAGES
PANE L_MARK_X
PANEL_CHOICE_STRING
PANE L_MARK_X S
PANEL_CHOICE_STRINGS
PANEL_MARK_Y
PANEL_CHOICE_X
PANEL_MARK_YS
PANEL_CHOICE_XS
PANEL_MENU_MARK_IMAGE
PANEL_CHOICE_Y
PANEL_MENU_NOMARK_IMAGE
PANEL_CHOICE_YS
PANEL_NOMARK_IMAGE
PANEL_CHOICES_BOLD
PANEL_NOMARK_IMAGES
PANEL_DISPLAY_LEVEL
PANEL_SHOW_MENU_MARK
PANEL_FEEDBACK
PANEL_TOGGLE_VALUE
PANEL LAYOUT
PANEL VALUE
Slider Item Attributes
PANEL_MIN_VALUE
PANEL SHOW RANGE P ANEL VALUE
PANEL_MAX_VALUE
PANEL SHOW_VALUE PANEL_VALUE_FONT
PANEL NOTIFY LEVEL
PANEL SLIDER WIDTH
©sun
microsystems
Revision A, of May 9,1988
Chapter 9 — Panels 157
Text Item Attributes
PANEL MASK CHAR
PANEL_VALUE_DISPLAY LENGTH
PANEL_NOTIFY_LEVEL
PANEL_VALUE
PANEL_NOTIFY_STRING
PANEL_VALUE_STORED LENGTH
PANE L_VALUE_FONT
Revision A, of May 9, 1988
158 SunView 1 Programmer’s Guide
9.1. Introduction to Panels Panels contain items through which the user interacts with a program. Panels are
and Panel Items quite flexible; you can use them to model a variety of things, including;
□ a form consisting mainly of text items;
□ a message window containing status or error messages;
□ a complex control panel containing items and menus of many types.
Panels need not be limited to the size of the subwindow they appear in. By
attaching scrollbars to a panel, you can show a large panel within a smaller
subwindow. The user can then bring the area of interest into view by means of
the scrollbars.
There are six basic types of panel items: messages, buttons, choices, toggles,
text and sliders. Items are made up of one or more displayable components. One
component shared by all item types is the label. An item label is either a string
or a graphic image (i.e., a pointer to a pixrect). Button, choice, toggle, and text
items also have a menu component. Thus the user may interact with most items
in either of two ways: by selecting the item directly or by selecting from the
item’s menu.
Each item type is introduced briefly below.
Message Items The only visible component of a message item is a label, which may be an image
or a string in a specified font. Message items are useful for annotations of all
kinds, including titles, comments, descriptions, pictures, and dynamic status mes¬
sages.
Message items are selectable, and you may specify a notify procedure to be
called when the item is selected.
Button Items Button items allow the user of a program to initiate commands. Buttons, like
message items, have a label, are selectable, and have a notify procedure. Button
items differ from message items in that they have visible feedback for preview¬
ing and accepting the selection.
Choice Items Choice items allow the user to select one choice from a list. The displayed form
of a choice item can vary radically, depending on how you set its attributes. A
choice item can be presented as:
□ a horizontal or vertical list of choices, with all choices visible and the current
choice indicated by a marie (such as a checkmark);
□ a horizontal or vertical list of choices, with all choices visible and the current
choice in reverse-video;
□ a “cycle item”, or list of choices with only the current choice visible. Select¬
ing the item causes the next choice in the list to be selected and displayed;
□ a dial, knob or switch with a pointer of some sort which turns to indicate one
of several choices;
□ a place holder for a pop-up menu, with only the label visible until the menu
button is pressed.
Revision A, of May 9,1988
Chapter 9 — Panels 159
Behind this flexibility of presentation lies a uniform structure consisting of a
label, a list of choices, and, optionally, a corresponding lists of on-marks and
off-marks used to indicate which choice is currently selected.
Toggle Items In appearance and structure, toggle items are identical to choice items. The
difference lies in the behavior of the two types of items when selected. In a
choice item exactly one element of the list is selected, or current, at a time. A
toggle item, on the other hand, is best understood as a list of elements which
behave as toggles: each choice may be either on or off, independently of the
other choices. Selecting a choice causes it to change state. There is no concept
of a single current choice; at any given time all, some, or none of the choices
may be selected.
Text Items Text items are basically type-in fields with optional labels and menus. You can
specify that your notify procedure be called on each character typed in, only on
specified characters, or not at all. This allows an application such as a forms-
entry program to process input on a per character, per field, or per screen basis.
Slider Items Slider items allow the graphical representation and selection of a value within a
range. They are appropriate for situations where it is desired to make fine adjust¬
ments over a continuous range of values. A familiar model would be a horizontal
volume control lever on a stereo panel.
9.2. Basic Panel Routines This section covers basic panel usage, including creating and sizing panels, creat¬
ing and positioning panel items, modifying and retrieving the attributes for
panels and panel items, and destroying panel items.
Creating and Sizing Panels Like all windows in SunView, panels are created by calling the window creation
routine with the appropriate type parameter:
Panel panel;
panel = window_create(frame, PANEL, 0);
< _
The above call will produce a panel which extends to the bottom and right edges
of the frame. You can specify the panel’s dimensions explicitly in character
units via WlN_COLUMNS and WIN_R0WS, or in pixel units via WIN_WIDTH
and WIN HEIGHT. 51
51 For a fuller discussion of subwindow sizing and layout see are in Chapter 4, Using Windows.
Revision A, of May 9,1988
160 Sun View 1 Programmer’s Guide
Creating and Positioning
Panel Items
Explicit Item Positioning
Often you want the panel to be just high enough to encompass all of the items
within it. After creating all of the items, and before creating any other subwin¬
dows in the frame, set the height of the panel by calling the macro
window_f it_height (). This macro will compute the lowest point occu¬
pied by any of the panel’s items and set the panel height to that point plus a bot¬
tom margin of four pixels. The macros window_fit_width() to set the
width, and window_f it () to set both the height and the width, are also pro¬
vided.
To create a panel item, call:
Panel_item
panel_create_item(panel, item_type, attributes)
Panel panel;
<itemtype> item_type;
<attribute-list> attributes;
Values for item_type must be one of PANEL_MESSAGE, PANEL_BUTTON,
panel_choice|PANEL_CYCLE,PANEL_TOGGLE,PANEL_TEXT, or
PANEL_SLIDER.
The position of items within the panel may be specified explicitly by means of
the attributes PANEL_ITEM_X and PANEL_ITEM_Y . 52 PANEL_ITEM_X sets
the left edge of the item’s rectangle (the rectangle which encloses the item’s label
and value). PANEL_ITEM_Y sets the top edge of the item’s rectangle.
All coordinate specification attributes interpret their values in pixel units. For
simple panels and forms which do not make heavy use of images and have only
one text font, it is usually more convenient to specify positions in character units
— columns and rows rather than x’s and y’s. You can specify positions in char¬
acter units with the ATTR_ROW () and ATTR_COL () macros , 53 which interpret
their arguments as rows or columns, respectively, and convert the value to the
corresponding number of pixels, based on the panel’s font, as specified by
WIN_FONT. Compare the two calls below:
panel_create_item (panel, PANEL_MESSAGE f
PANEL__LABEL_STRING, "Hi ! ",
PANEL_ITEM__X, 10,
PANEL_ITEM_Y, 20,
0 );
52 Many attributes, such as those relating to item positioning, apply across all of the item types; these are
called generic attributes. A comprehensive summary of these generic attributes is given in the Generic Item
Attributes table in are in Chapter 19, SunView Interface Summary.
53 ATTR ROW () and ATTR COL () are described fully in Chapter 18, Attribute Utilities.
microsystems
Revision A, of May 9,1988
Chapter 9 — Panels 161
panel_create_item(panel, PANEL_MESSAGE,
PANEL_LABEL_STRING, "Hi!",
PANEL_ITEM_X, ATTR_COL(10),
PANEL_ITEM_Y, ATTR_ROW(20),
0 );
The first will place the item at pixel location (10,20), while the second will place
the item at row 20, column 10.
NOTE The value computed for ATTR_ROW () includes the top margin, given by
WIN_T0P_MARGIN, and the value computed for ATTR_COL () includes the
left margin, given by WIN_LEFT_MARGIN. The alternate macros
ATTR_ROWS () and ATTR_COLS () are also provided, which compute values
that do not include the margins.
Default Item Positioning If you create an item without specifying its position, it is placed just to the right
of the item on the “lowest row” of the panel, where lowest row is defined as the
maximum y-coordinate ( PANEL_ITEM_Y ) of all the items. So in the absence
of specific instructions, items will be placed within the panel in reading order as
they are created: beginning four pixels in from the left and four pixels down
from the top, items are located from left to right, top to bottom. If an item will
not fit on a row, and more of the item would be visible on the next row, it will be
placed on the next row. The number of pixels left blank between items on a row
may be specified by PANEL_ITEM_X_GAP, which has a default value of 10.
The number of pixels left blank between rows of items may be specified by
PANEL_ITEM_Y_GAP, which has a default value of 5.
The default position for the next item is computed after an item is created. But if
a client calls panel_set () after creating an item in such a way that the
enclosing rectangle of the item is altered, the default position for the next item
will not be recomputed. So, for example,
item = panel_create_item(panel, PANEL_MESSAGE, 0);
panel_set(item, PANEL_LABEL_STRING, "Hi", 0);
iteml - panel_create_item(panel, PANEL_MESSAGE,
PANEL_LABEL_STRING, "There",
0 );
will result in There overlapping Hi.
CAUTION Choice items currently have problems with item “creep.” Each time the label
of a choice item is set, the position of the item will be evaluated. If the value’s
position has not been fixed (with VALUE_x/Y), the value is positioned after the
label. The problem is that the label is baseline-adjusted for a choice item. If the
item position is not given when the label is set, the choice item will creep down
because of the baseline adjustment.
microsystems
Revision A, of May 9, 1988
162 SunView 1 Programmer’s Guide
Laying Out Components Within
an Item
Modifying Attributes
You may also specify the layout of the various components within an item, by
means of the attributes PANEL_LABEL_X, PANEL_LABEL_Y,
PANEL_VALUE_X, panel_value_Y, etc. If the components are not expli¬
citly positioned, then the value is placed either eight pixels to the right of the
label, if p anel_layout is PANEL_HORi ZONTAL (the default), or four pixels
below the label, if PANEL_LAYOUT is PANEL_VERTICAL.
This section describes how to modify the values of attributes of panels or indivi¬
dual panel items which have already been created.
Since panels are a type of window, their attributes are set with window_set ().
To set attributes of panel items, use:
panel_set(item, attributes)
Panel_item item;
<attribute-list> attributes;
A macro is provided to ease the syntax for the common operation of setting an
item’s value (attribute PANEL_VALUE ):
panel_set_value(item, value)
Panel_item item;
caddr_t value;
Several examples of setting attributes are given here; for a complete list of the
attributes applying to panels and items, see the tables in are in Chapter 19, Sun-
View Interface Summary.
To move a panel’s caret to the text item name_item:
window_set(panel,
PANEL_CARET_I TEM,
name item, 0);
To set the value of the choice item f ormat_item to the third choice (choices
are zero-based):
--
Panel_itern format_item;
panel_set_value (format__item, 2);
The first call below creates a message which is initially “hidden” (not displayed
on the screen); the second call displays the message:
Xr microsystems
Revision A, of May 9,1988
Chapter 9 — Panels 163
NOTE The values for string-valued attributes are dynamically allocated when they are
set (at creation time or later). If a previous value was present, it is freed after the
new string is allocated. This is in contrast to the storage-allocation policy for
retrieving attributes, described in the section titled Retrieving Attributes.
Panel-Wide Item Attributes Some attributes which apply to items may be set for all items in the panel by set¬
ting them when the panel is created. Such attributes include whether items have
> menus, whether item labels appear in bold, whether items are laid out vertically
or horizontally, and whether items are automatically repainted when their attri¬
butes are modified. 54 For example, the call:
r
\
panel = window_create(frame, PANEL
PANEL_SHOW_MENU,
FALSE,
PANEL_LABEL_BOLD,
TRUE,
PANEL_LAYOUT,
P ANEL__VERT I CAL,
PANEL PAINT,
PANEL_NONE,
s,
0);
— ___/
overrides the defaults for all the attributes mentioned: any items subsequently
created in that panel will not have menus, will have their labels printed in bold
and their components laid out vertically, and will not be repainted automatically
when their attributes are modified.
NOTE When you set the attribute PANEL_LAYOUT, it will only affect the components
in each item, not the items themselves. That is, all items in a panel will not be
layed out vertically.
Keep in mind that he panel-wide item attributes mentioned above are only used
to supply default values for items which are subsequently created. This means,
for example, that you cannot change all the item labels to bold by first creating
the items and then setting PANEL_LABEL_BOLD to TRUE for the panel.
Retrieving Attributes Use window_get () to retrieve attributes for a panel. To retrieve attributes
applying to panel items, use:
caddr_t
panel_get(item, attribute!, optional_arg])
Panel_item item;
Panel_attribute attribute;
Panel_attribute optional_arg;
A macro is provided to ease the syntax for the common operation of getting an
item’s value (attribute PANEL_VALUE ):
54 For a complete list of panel-wide item attributes, see the Panel Attributes table in are in Chapter 19,
SunView Interface Summary.
microsystems
Revision A, of May 9,1988
164 SunView 1 Programmer’s Guide
Destroying Panel Items
caddr_t
panel_get__value (item, value)
Panel__item item;
caddr_t value;
Since the *_get () routines are used to retrieve attributes of all types, you
should coerce the value returned into the type appropriate to the attribute being
retrieved, as in the examples below.
To find out whether an item is currently being displayed on the screen:
L
int displayed;
displayed = (int)panel_get(item, PANEL_SHOW_ITEM);
>
_ >
To find out whether the caret in a panel is blinking or non-blinking:
int blinking;
blinking - (int) window__get (panel, PANEL_BLINK_CARET);
To get the image for a choice item’s third (counting from zero) choice:
r
<
Pixrect *image;
image = (Pixrect *)panel_get (item, PANEL__CHOICE_IMAGE, 2);
J
The above example illustrates the use of the optional_arg argument, which
is used for only a few item attributes.
NOTE panel_get () does not dynamically allocate storage for the values it returns.
If the value returned is a pointer, it points directly into the panel’s private data. It
is your responsibility to copy the information pointed to. The policy for setting
attributes is different: the values for string-valued attributes are dynamically
allocated (see the note above under Modifying Attributes).
To destroy a panel item (and free its associated dynamic storage), call:
panel_destroy_item(item) ;
Panel item item;
microsystems
Revision A, of May 9, 1988
Chapter 9 — Panels 165
9.3. Using Scrollbars With A scrollable panel is a large panel which can be viewed through a smaller
Panels subwindow by means of scrollbars.
Creating Scrollbars Scrollbars come in two orientations: vertical and horizontal. The call below
creates a panel with both vertical and horizontal scrollbars (as would be desirable
in a long, many-columned table, for example):
C ---\
panel = window_create(frame, PANEL,
WIN_VERTICAL_SCROLLBAR, scrollbar_create(0),
WIN_HORIZONTAL_SCROLLBAR, scrollbar_create(0),
0 );
v_^
The values of the attributes WlN_VERTICAL_SCROLLBAR and
win_HORIZONTAL_SCROLLBAR are the scrollbars which are returned by the
scrollbar_create () calls. 55
Commonly the scrollbar will remain attached to the panel for the duration of the
panel’s existence, and there will be no need to modify the scrollbar’s attributes.
In this simple case, there is no need to save the handle returned by
scrollbar_create (). If you desire to destroy the scrollbar, modify its
attributes, or detach it from one panel and attach it to another, you must either
save the handle or retrieve it from the panel. 56 For example, to destroy a panel’s
vertical scrollbar:
—
scrollbar_destroy (panel_get (panel, WIN_VERTICAL_SCROLLBAR) ) ;
panel_set(panel, WIN_VERTICAL_SCROLLBAR, NULL, 0);
v_>
Scrolling Panels Which Often panels are used to display information for browsing, iconedit(l), for
Change Size example, uses a popup panel to allow the user to browse through the images in a
directory. The easiest way to do this is to create the panel items anew each time
different information is displayed. For example, the iconedit function which
fills the browsing panel first destroys any existing panel items, then creates an
item for each image found.
If you are going to change the size of the panel in this way, you must inform the
scrollbar of the new size by calling the function:
panel_update_scrolling_size(panel)
Panel panel;
55 The call scrollbar_create (0) produces a default scrollbar. It is usually best to create a default
scrollbar and let the user specify how it looks via defaultsedit. You can, of course, override the user’s default
settings by explicitly setting the scrollbar’s attributes. For a complete list of scrollbar attributes see Chapter 19,
SunView Interface Summary .
56 In order to save the scrollbar’s handle or reference any scrollbar attributes you must include the file
<suntool/scrollbar.h>.
microsystems
Revision A, of May 9, 1988
166 SunView 1 Programmer’s Guide
The correct time to call panel_update_scrolling_size () is after you
have created all the items and given them labels. If you don’t update the
scrollbar’s idea of the panel’s size, the size of the scrollbar’s bubble will be
wrong.
You may want the same panel to be scrollable at one time, and not scrollable at
another. The code fragment below illustrates how this can be accomplished by
attaching and detaching a scrollbar from a panel:
Detaching Scrollbars from
Panels
panel = window_create(frame, PANEL, 0) ;
(create items , do any other processing...)
/* create scrollbar and attach it to panel */
sb = scrollbar_create(0);
panel_set(panel, WIN_VERTICAL_SCROLLBAR, sb, 0);
(panelfunctions with scrollbar...)
/* now detach scrollbar from panel */
panel_set(panel, WIN_VERTICAL_SCROLLBAR, NULL, 0);
(panel functions without scrollbar...)
scrollbar__destroy (sb) ;
^ ___ )
Note that the two packages are to be considered from the application’s viewpoint
as independent packages which can be used together. The application, not the
panel package, has the responsibility for creating any scrollbars. In order to free
the application of the responsibility for destroying the scrollbar, panels, when
they are destroyed, destroy any scrollbars attached to them. However, detaching
a scrollbar from a panel, as in the above example, does not cause that scrollbar to
be destroyed. The same scrollbar may be attached and detached from any
number of panels any number of times.
The sections which follow discuss the six item types in detail.
Revision A, of May 9, 1988
Chapter 9 — Panels 167
9.4. Messages
Example
9.5. Buttons
Button Selection
Button Notification
Messages are the simplest of the item types. Their only visible component is
their label. They have no value or menu.
Message items, like buttons, are selectable and can have notify procedures. The
selection behavior of messages differs from that of buttons in that no feedback is
given to the user when a message is selected.
In the following example, two message items are used together to give a warning
message:
This action ui11 cause unsaved edits to be lost.
static short stop_array[] = {
♦include "stopsign.image"
};
mpr_static (stopsign, 64, 64, 1, stop__array) ;
panel_create_item (panel, PANEL_MESSAGE,
PANEL__LABE L_I MAGE, & s t op s i gn,
0 );
panel_create_item (panel, PANEL_MESSAGE,
PANEL_LABEL_STRING,
"This action will cause unsaved edits to be lost.",
0 );
You may change the label for a message item (as for any type of item) via
PANEL_LABEL_STRING or PANEL_LABEL_IMAGE.
Button items have a label and a menu, but no value.
When the left mouse button is pressed over a button item, the item’s rectangle is
inverted. When the mouse button is released over a button item, the item’s rec¬
tangle is painted with a grey background, indicating that the item has been
selected and the command is being executed. The grey background is cleared
upon return from the notify procedure.
The procedure specified via the attribute PANEL_NOTlFY_PROC will be called
when the item is selected. The form of the notify procedure for a button is:
button_notify_jproc (item, event)
Panel__item item;
Event *event
microsystems
Revision A, of May 9,1988
168 SunView 1 Programmer’s Guide
Button Image Creation Utility A routine is provided to create a standardized, button-like image from a string:
Pixrect *
panel_button_image(panel, string, width, font)
Panel panel;
char *string;
int width;
Pixfont *font;
where width indicates the width of the button, in character units. The value
returned is a pointer to a pixrect showing the string with a border drawn around
it. If width is greater than the length of string, the string will be centered in
the wider border, otherwise the border will be just wide enough to contain the
entire string (i.e., the string will not be clipped) The font is given by font — if
NULL, the font for panel is used.
Examples The first example renders the string in the default system font, found in
/usr/lib/fonts/fixedwidthfonts/screen.r.13:
[Reset 1 ]
f -\
panel_create_item (panel, PANEL_BUTTON,
PANEL_NOTIFY_PROC, quit_proc,
PANEL_LABEL_IMAGE, panel_button_image(panel, "Reset", 0, 0),
0 );
s_ )
The button below has a bold font and a seven character wide border:
[ Reset j
—
bold = pf_open ("/usr/lib/fonts/fixedwidthfonts/screen.b. 12") ;
panel_create_item (panel, PANEL_BUTTON,
PANEL_NOTIFY_PROC, quit_proc,
PANEL_LABEL_IMAGE, panel_button_image(panel,"Reset",7,bold),
0 );
s_>
It is often useful to associate a menu with a button. Figure 9-1 illustrates a but¬
ton representing an online manual. The menu over the button allows the user to
bring up the text for the different chapters:
Figure 9-1 Associating a Menu With a Button
Introduction
Pixuins
Cursors
SunYieu Model
Text Subuindous
Icons
Windous
Zl Panels
Scrollbars
Canvases
TTY Subuindous
Selection Service 1
Input
Menus
Notifier |
Sun
Manual
microsystems
Revision A, of May 9,1988
Chapter 9 — Panels 169
To do this, you must write your own event procedure, as described in Section
9.13, Event Handling. On receiving a right mouse button down event, display
the menu and take the appropriate action depending on which menu item die user
selects. For all other events, call the panel’s default event procedure.
Here is the code to create the menu and the button, and the event procedure to
display the menu:
-N
static short book_array[] = {
♦include "book.image"
};
mpr_static(book, 64, 64, 1, book_array);
Menu menu = menu_create( MENU_NCOLS, 3, MENU_STRINGS,
"Introduction",
"SunView Model"
"Windows",
"Canvases",
"Input",
0 );
"Pixwins",
"Text Subwindows"
"Panels",
"TTY Subwindows",
"Menus",
"Cursors",
"Icons",
"Scrollbars",
"Selection Service"
"Notifier", 0,
panel_create_item(panel, PANEL_BUTTON,
PANEL_LABEL_IMAGE, &book,
PANEL_EVENT_PROC, handle_panel_event
0 );
handle_j?anel_event (item, event)
Panel_item item;
Event *event;
if (event_action(event) ==
MS_RIGHT St & event_is_down (event) ) {
int chapter = menu_show(book_menu, panel, event, 0);
switch (chapter) {
case 1: /* Introduction */ break;
case 2: /* Pixwins */ break;
case 15: /* Notifier */ break
} else
panel_default_handle__event (item, event) ;
Revision A, of May 9,1988
170 SunView 1 Programmer’s Guide
9.6. Choices
Displaying Choice Items
Choice items are the most flexible — and complex — item types. 57 Besides the
label, they are composed of:
□ a list of either image or string choices (specified via the attributes
PANEL_CHOICE_IMAGES or PANEL_CHOICE_STRINGS ).
□ a list of mark-images — images to be displayed when the corresponding
choice is selected ( PANEL_MARK_IMAGES ). The default marie is a push¬
button with the center inverted.
□ a list of nomark-images — images to be displayed when the corresponding
choice is not selected ( PANEL_NOMARK_iMAGES ). The default nomarie
image is a non-inverted push-button.
The choices are numbered beginning with zero, and there is no restriction on the
number of choices a single choice item may have.
The attribute PANEL_DISPLAY_LEVEL determines which of an item’s choices
are actually displayed on the screen. The display level may be set to:
□ PANEL_ALL, (the default) all choices are shown;
□ PANEL_CURRENT, only the current choice is shown;
o PANEL_NONE, no choices are shown. Since the only way of selecting a
choice is through the menu, this becomes a label with an associated pop up
menu.
If the display level is panel_CURRENT or panel_all, the choices are placed
by default horizontally after the label. You can lay them out vertically below the
label by setting PANEL__LAYOUT to PANEL_VERTICAL. If you want to place
the choices or marks more precisely — in order to model a switch or some other
special form — you can do so by setting the appropriate attribute, such as
PANEL_CHOICE_XS,PANEL_CHOICE_YS, PANEL_MARK_XS,
PANEL_MARK_YS, etc.
A few words about using the various lists in choice items. The list you give for
PANEL_CHOICE_STRINGS (or PANEL_CHOICE_IMAGES ) determines the
item’s choices. 58
57 For a complete list of the attributes applicable to choice items, see the Choice Item Attributes table in arc
in Chapter 19, SunView Interface Summary.
58 You must specify at least one choice, so the least you can specify is a single choice consisting of the null
string.
microsystems
Revision A, of May 9,1988
Chapter 9 — Panels 171
The parallel lists PANEL_CHOICE_FONTS, PANEL_MARK_IMAGES,
PANEL_NOMARK_IMAGE S, P ANEL_MARK_XS, PANEL_MARK_YS,
PANEL_CH0ICE_XS, and PANEL_CHOICE_YS are interpreted with respect to
the list of choices. For example, the first font given for
PANEL_CHOiCE_FONTS will be used to print the first string given for
panel_CHOICE_STRINGS, the second font will be used for the second string,
and so on.
The item below, taken from iconedit, shows how parallel lists can be abbrevi¬
ated:
□
n
panel__create_it em (iced_panel
PANEL_MARK_IMAGES f
P ANEL_NOMARK_I MAGES,
PANE L__CHO I CE__I MAGES ,
PANEL_VALUE,
PANEL_CHOICE_XS,
PANEL_MARK_XS,
PANEL_CHOICE_YS,
PANEL_MARK_YS,
PANEL__NOT IFY_PROC f
0 );
s_
PANEL__CHOI CE,
&down__triangle, 0,
0 ,
&square_white, &square_25,
&square_root, &square__50,
&square_75, &square__black, 0,
2 ,
30, 60, 90, 120, 150, 180, 0,
34, 64, 94, 124, 154, 184, 0,
345, 0,
363, 0,
proo f_ba c kground_pro c,
The item has six choices, representing the six available background patterns for
the proof area. Note, however, that three of the lists, —
PANEL_MARK_IMAGES, PANEL_CHOICE_YS and PANEL_MARK_YS all
have only one element. When any of the parallel lists are abbreviated in this
way, the last element given will be used for the remainder of the choices. So, the
345, 0 in the example above serves as shorthand for 345, 345, 345,
345, 345, 345, 0. All the choice images will appear at y coordinate 345,
all the marie images will appear at y coordinate 363, and all the choices will have
down_t riangle as their marie image.
NOTE You can’t specify that a choice or mark-image appear atx = 0 or y = 0 by using
the attributes PANEL_CHOICE_XS, PANEL_CHOICE_YS,
PANEL_MARK_xs or PANEL_mark_YS . Since these attributes take null-
terminated lists as values, the zero would be interpreted as the terminator for the
list. You may achieve the desired effect by setting the positions individually,
with the attributes PANEL_CHOICE_X, PANEL_CHOICE_Y,
PANEL_MARK_X, or PANEL_MARK_Y, which take as values the number of the
choice or mark, followed by the desired position.
Revision A, of May 9, 1988
172 SunView 1 Programmer’s Guide
Choice Selection
Choice Notification
Choice Value
Choice Menus
The user can make a selection from a choice item either by selecting the desired
choice directly, by selecting from the associated menu, or by selecting the label,
which causes the current choice to advance to the next choice (or backup to the
previous choice if the shift key is pressed while selecting);
Feedback for choice items comes in two flavors — inverted, in which the current
choice is shown in reverse video, and marked, in which the current choice is indi¬
cated by the presence of a distinguishing mark, such as a check-mark or arrow.
Specified the type of feedback you want by setting panel_feedback to either
PANEL_INVERTED or PANEL_MARKED.
You may also disable feedback entirely, by setting PANEL_FEEDBACK to
PANEL_NONE.
The default feedback is PANEL_MARKED, unless the item’s display level is
current, in which case the feedback is P ANEL_NONE.
The procedure specified via the attribute PANEL_NOTlFY_PROC will be called
when the item is selected. Choice notify procedures are passed the item, the
current value of the item, and the event which caused notification:
choice_notify__proc (item, value, event)
Panel_item item;
int value;
Event *event;
The value passed to the notify procedure is the ordinal number corresponding to
the current choice (the choice which the user has just selected). The first choice
has ordinal number zero.
Choice and Toggle items are the only item types for which a menu appears by
default. To disable the menu for a particular item, set PANEL_SHOW_MENU for
that item to FALSE.
Choice item menus may be used to represent either a simple menu or a checklist.
The former is a menu of commands, which gives no indication of which com¬
mand was executed last; the latter is a menu of choices with a check-mark indi¬
cating the current choice. Set PANEL_SHOW_MENU_MARK to FALSE to obtain
a simple menu, or TRUE to get a checklist
NOTE The number of menu choices, if set by P ANEL_MENU_CHOICE_STRINGS or
PANEL_MENU_CH0ICE_IMAGES, must be equal to the number of choices for
the item.
microsystems
Revision A, of May 9,1988
Chapter 9 — Panels 173
Examples As a basis for our examples we’ll take the item in iconedit which allows the
user to select the drawing mode. The item could have been presented in several
different forms.
The simplest call would specify the label and choices as strings, and take the
defaults for all other attributes. All the choices will be displayed, and the feed¬
back will be marked, with push-buttons for the mark images:
Drawing Mode: 0 Points Bune 0 Rectangle 0 Circle 0Text
r
\
panel_create_item (panel.
PANEL_CHOICE,
PANEL_LABEL_STRING,
"Drawing Mode:",
PANEL_CHOICE_STRINGS,
"Points", "Line", "Rectangle",
"Circle", "Text", 0,
0);
You can specify a custom mark, such as this small pointer, to indicate the current
choice:
Drawing Mode: Points »Line Rectangle Circle Text
r
\
static short pointer_array[] = {
#include "pointer.pr"
};
mpr_static(pointer, 16,
16, 1, pointer_array);
panel_create_item(panel,
PANEL_CHOICE,
P ANEL_LABEL_STRI NG,
"Drawing
Mode:",
PANE L_MARK_I MAGE S,
^pointer.
0,
PANEL_NOMARK_IMAGES,
0,
PANEL_CHOICE_STRINGS
, "Points",
"Line", "Rectangle",
"Circle",
"Text", 0,
0);
V,
-J
Setting PANEL_FEEDBACK to PANEL_INVERTED produces:
Drawing Mode: Points IM'it-J Rectangle Circle Text
Revision A, of May 9,1988
174 SunView 1 Programmer’s Guide
Often space on the panel is limited, and it is appropriate to save space by only
showing the currently selected choice. You can do that by disabling feedback
and displaying only the current choice:
Drawing Mode: Line
r
panel__create__item (panel,
PANEL_CHOICE,
PANE L_LABEL_STRI NG,
"Drawing Mode:",
PANEL_CHOICE_STRINGS,
"Points", "Line", "Rectangle",
"Circle", "Text", 0,
PANEL_DISPLAY_LEVEL,
PANEL_CURRENT,
PANEL FEEDBACK,
PANEL_NONE,
0);
_y
Such an item has the drawback of looking to the user like a text item. One solu¬
tion to this problem is to provide a distinguishing marie which clearly indicates
the item’s type, as in:
Drawing Mode: OLine
The double-arrow image suggests a cycling motion, indicating to the user that the
item is a choice item with more choices available. To get the cycle image, use
the special item type PANEL_CYCLE: 59
r
panel_create_item (panel,
PANE L__CY CLE,
\
PANEL_LABEL_STRING,
"Drawing Mode:",
PANEL_CHOICE_STRINGS,
"Points", "Line", "Rectangle",
"Circle", "Text", 0,
0);
V
-^
59 Note that a cycle item is simply a choice item with some attributes initialized — the display level is set to
current and the on-mark is set to the cycle image. Once created, cycle items behave in exactly the same way as
choice items.
XT microsystems
Revision A, of May 9,1988
Chapter 9 — Panels 175
With some effort, you can use a choice item to model a dial, as in Figure 9-2.
Figure 9-2 A Dial-Like Choice Item
Rect
Line
Points
Circle
Text
Drawing Mode
The way to make a such a dial is to make an image for each dial setting, and use
these images as the on-marks. Place the on-marks and the choices explicitly —
the on-marks in the center, forming the dial, and the choices around the dial’s
perimeter:
panel_create_item (panel,
PANEL_CHOICE,
P ANE L_CHO I CE__S TRING S,
"Points' 1 , "Line", "Rect",
"Circle", "Text", 0,
PANEL_MARK_IMAGES,
&dial__l, &dial_2, &dial_3,
&dial 4, &dial 5, 0,
PANE L_NOMARK_IMAGES,
0 ,
PANEL_CHOICE_XS,
7, 34, 82, 133, 145, 0,
PANEL_CHOICE_YS,
53, 33, 20, 33, 53, 0,
PANEL_MARK_XS,
66, 0,
PANEL_MARK_YS,
O
o
PANEL_LABEL_STRING,
"Drawing Mode",
P ANEL_LABEL__X,
30,
PANEL_LABEL_Y,
65,
PANE L_LABEL_FONT,
pf_open ("/usr/lib/fonts/fixedwidthfonts/gallant .r. 19") ,
0 ); ‘
V-_---/
The form which is actually used in showniconeditis Figure 9-3. It employs
vertical layout, images for the choices, and strings for the menu:
Figure 9-3 iconedit ’s Drawing Mode Choice Item
□
o
abc
Points
Line
Rectangle
Circle
Text
XT microsystems
Revision A, of May 9,1988
176 SunView 1 Programmer’s Guide
r
1
panel_create__item (panel, PANEL_
CHOICE,
PANEL_LAYOUT,
_ PANE L_VERT I CAL ,
PANE L__CHO I CE_I MAGES ,
Spoints, &line, &rectangle,
Scircle, &text, 0,
PANE L_MENU_CHO I CE__S TRINGS,
"Points", "Line", "Rectangle",
"Circle", "Text", 0,
P ANE L_MARK_IMAGES,
&drawing_hand, 0,
PANEL NOMARK_IMAGES,
0);
0,
V_
-j
9.7. Toggles
Displaying Toggles
Toggle Selection
Toggle Notification
Toggle Value
Toggle items are identical in structure to choice items — they have a label and
parallel lists of choices, on-marks and off-maries. They differ from choice items
in certain aspects of their display options, their selection behavior and the
interpretation of their value. These differences are highlighted below.
Toggle items may have a PANEL_DISPLAY_LEVEL of either PANEL_ALL —
all choices visible, or PANEL_NONE — no choices visible. The default is
PANEL_ALL.
Since there is no notion of the current choice for a toggle item, a display level of
PANEL_CURRENT is not allowed.
Toggle items, like choice items, may have either inverted or marked feedback,
depending on the value of PANEL_FEEDBACK. The default is
PANEL_MARKED. For inverted feedback, specify PANEL_INVERTED.
PANEL_NONE is not allowed.
Toggle items may be selected by clicking on the desired choice or through the
menu. Selecting a choice causes that choice to toggle on or off (change state);
other choices are not affected.
If there is only one choice, it may be toggled by selecting the label; if there is
more than one choice, selecting the label has no effect
The parameters for the notify procedure are the same as for choice items except
that the value passed is a bit mask instead of an integer:
toggle_notify_proc(item, value, event)
Panel_item item;
unsigned int value;
Event *event;
The value passed to the notify procedure is a bit mask representing the state of
the first 32 choices — if a bit is one, then the corresponding choice is on, if a bit
is zero, then the corresponding choice is off. (The least significant bit is bit zero,
which maps to choice zero.)
#sun
Xr microsystems
Revision A, of May 9, 1988
Chapter 9 — Panels 177
Example
Figure 9-4 illustrates an item which lets you set the -/, -r, or -a flags for the Is
command:
Figure 9-4 A Toggle Item
Format Options:
S' Long
□ Reverse
Ef Show all files
format_item = panel_create_item(panel, PANEL_TOGGLE,
PANEL_LABEL_STRING,
"Format Options:",
P ANEL__LAY OUT,
PANEL_VERTICAL,
PANEL__CHOICE_STRINGS,
"Long",
"Reverse",
"Show all files",
0 ,
0, TRUE,
PANE L_TOGGLE__VALUE,
P ANEL_TOGGLE_VALUE,
2, TRUE,
PANEL NOTIFY PROC,
0);
format_notify_proc,
You can get or set the value of a particular choice — including choices beyond
the first 32 — with PANEL_TOGGLE_VALUE. When used to set the value, this
attribute takes two values: the index of the choice to set, and the desired value.
In the above example, PANEL_TOGGLE_VALUE is used to initialize the first and
third choices to TRUE. To find out the value of the third choice, you would call:
-—--
value = (int) panel_get(format_item, PANEL_TOGGLE_VALUE, 2);
-—--
You can also use the attribute PANEL__VALUE to set and get the state of a
toggle’s choices. As mentioned on the previous page, a toggle’s value is a bit
mask representing the state of the first 32 choices. To facilitate working with the
value, you might first define names corresponding to each choices, and a macro
to test for the corresponding bit in the value, like this:
f
#define
LONG
0
\
#define
REVERSE
1
#define
SHOW_ALL
2
#define
toggle_bit
__on (value, bit)
((value) & (1 « (bit)))
v ,
__>
You can then use the value in the notify procedure, as in:
Revision A, of May 9,1988
178 SunView 1 Programmer’s Guide
Toggle Menus
9.8. Text
Displaying Text Items
- ,
format_notify_proc(format_item, value, event)
Panel_item format_item;
unsigned int value;
Event *event?
1
if (toggle_bit_on(value, LONG)) {
1
if (toggle_bit_on(value, REVERSE)) {
1
if (toggle_bit_on(value, SHOW_ALL)) {
}
}
.___
Or you can retrieve the value outside of the notify procedure, as in:
f -
>
unsigned value;
value = panel_get_value (format__item) ;
if (toggle_bit__on (value, LONG)) {
}
_ _ _—— -
>
The menu has as many lines as choices, and each line toggles when selected. In
other words, the marie indicating “on” (PANEL_MENU_MARK_IMAGE) is alter¬
nated with the marie signifying “off’ (PANEL_MENU_NOMARK_lMAGE) each
time the user selects a given line.
To disable the menu, set PANEL_SHOW_MENU to FALSE.
The value component of a text item is the string which the user enters and edits.
It is drawn on the screen just after the label, as in:
Name: Eduard G. Robinson
panel_create_item (panel, PANEL_TEXT,
PANEL_LABEL_STRING, "Name: ",
PANEL_VALUE, "Edward G. Robinson",
0 );
If PANEL_LAYOUT is set to PANEL_VERTICAL, overriding the default of
PANEL_HORl ZONTAL, the value will be placed below the label.
The number of characters of the text item’s value which are displayable on the
screen is set via PANEL_VALUE_DISPLAY_LENGTH, which defaults to 80
characters. When characters are entered beyond this length, the value string is
scrolled one character to the left, so that the most recently entered character is
Revision A, of May 9,1988
Chapter 9 — Panels 179
Text Selection
always visible. As the string scrolls to the left, the leftmost characters move out
of the visible display area. The presence of these temporarily hidden characters
is indicated by a small left-pointing triangle. So setting the display length to 12
in the above call would produce:
Name: < G. Robinson
As excess characters are deleted, the string is scrolled back to the right, until the
actual length becomes equal to the displayed length, and the entire string is visi¬
ble.
It is sometimes desirable to have a protected field where the user can enter
confidential information. The attribute P ANE L_MAS K_CHAR is provided for
this purpose. When the user enters a character, the character you have specified
as the value of panel_mask_CHAR will be displayed in place of the character
the user has typed. So setting PANEL_MASK_CHAR to “' *' ” would produce:
Passuord: ********
If you want to disable character echo entirely, so that the caret does not advance
and it is impossible to tell how many characters have been entered, use the space
character as the mask. You can remove the mask and display the actual value
string at any time by setting the mask to the null character.
The maximum number of characters which can be typed into a text item
(independently of how many are displayable) is set via the attribute
P ANEL_VALUE_STORED_LENGTH. Attempting to enter a character beyond
this limit causes the field to overflow, and the character is lost. The value string
is blinked to indicate to the user that the text item is not accepting any more char¬
acters.
The stored length, like the displayed length, defaults to 80 characters.
A panel may have several text items, exactly one of which is current at any given
time. The current text item is the one to which keyboard input is directed, and is
indicated by a caret at the end of the item’s value. (If PANEL_BLINK_CARET
is TRUE, the caret will blink as long as the cursor is in the panel.) Selection of a
text item (i.e. pressing and releasing the left mouse button anywhere within the
item’s rectangle) causes that item to become current. A text item also becomes
current if it is displayed after being hidden — i.e. if PANEL_SHOW_iTEM is set
to TRUE.
You can find out which text item has the caret, or give the caret to a specified text
item, by means of the panel attribute PANEL_CARET_ITEM. The call •
f ---\
window_set (panel, PANEL_CARET_ITEM, name__item, 0) ;
v____>
moves the caret to name item, while
microsystems
Revision A, of May 9,1988
180 SunView 1 Programmer’s Guide
Text Notification
-\
(Panel_item)window_get(panel, PANEL_CARET_ITEM);
_/
retrieves the item with the caret.
You can rotate the caret through the text items with the following two routines:
panel_advance_caret(panel)
Panel panel;
panel_backup_caret(panel)
Panel panel;
Advancing past the last text item places the caret at the first text item; backing up
past the first text item places the caret at the last text item.
The notification behavior of text items is rather more complex than that of the
other item types. You can control whether your notify procedure is called on
each input character or only on selected characters. If your notify procedure is
called, then the value it returns tells the panel package what to do — whether to
insert the character, advance to the next text item, etc.
When your notify procedure will be called is determined by the value of
PANEL_NOTlFY_LEVEL. Possible values are given in the following table.
Table 9-1 Text Item Notification
Notification Level
Causes Notify Procedure to be Called
PANEL_NONE
Never
P ANE L_NON__P R INTAB LE
On each non-printable input character
PANEL_SPECIFIED
If the input char is found in the string
given for the attribute
PANEL_NOTIFY_STRING
PANEL_ALL
On each input character
PANEL_NOTIFY_LEVEL defaults to PANEL_SPECIFIED, and
PANEL_N0TIFY_STRING defaults to \n\r\t (i.e., notification online-feed,
carriage-return and tab).
What happens when the user types a character? The panel package treats some
characters specially. I Meta-C l . 60 ( Meta-V 1 . and I Meta-X I are mapped to the Sun-
View functions I Copy 1 . 1 Paste I . and I Cut 1 . respectively. When the user types
these characters, the panel package notices them and performs the appropriate
operation, without passing them on to your notify procedure.
The user’s editing characters — erase, erase-word, and kill — are also treated
specially. If you have asked for the character by including it in
PANEL_N0TIFY_STRING, the panel package will call your notify procedure.
60 The Meta key is ( I .eft I or I Right I on the Sun-2 and Sun-3 keyboards. On the type 4 keyboard, the 1 Meta )
keys are marked with diamonds [ ♦ l
microsystems
Revision A, of May 9,1988
Chapter 9 — Panels 181
After the notify procedure returns, the appropriate editing operation will be
applied to the value string. (Note: the editing characters are never appended to
the value string, regardless of the return value of the notify procedure.)
Characters other than the special characters described above are treated as fol¬
lows. If your notify procedure is not called, then the character, if it is printable,
is appended to the value string. If it is not printable, it is ignored. If your notify
procedure is called, what happens to the value string, and whether the caret
moves to another text item, is determined by the notify procedure’s return value.
The following table shows the possible return values:
Table 9-2 Return Values for Text Item Notify Procedures
Value Returned
Action Caused
PANEL_INSERT
Character is appended to item’s value
PANEL__NEXT
Caret moves to next text item
PANELJPREVIOUS
Caret moves to previous text item
PANEL_NONE
Ignore the input character
If a non-printable character is inserted, it is appended to the value string, but
nothing is shown on the screen.
If you don’t specify your own notify procedure, the default procedure
panel_text_notif y () will be called at the appropriate time, as determined
by the setting of PANEL_NOTlFY_LEVEL. The procedure is shown below:
Panel_setting
panel_text_notify(item, event)
Panel_item item
Event *event
This procedure returns a panel setting enumeration which causes: 1) the caret to
move to the next text item on I RETURN 1 or 1 TAB 1 :2) the caret to move to the
previous text item on I SHIFT) [ RETURN) or I SHIFT) I TAB:) 3) printable char¬
acters to be inserted; and 4) all other characters to be discarded.
By writing your own notify procedure, you can tailor the notification behavior of
a given text item to support a variety of interface styles. On one extreme, you
may want to process each character as the user types it in. For a different appli¬
cation you may not care about the characters as they are typed in, and only want
to look at the value string in response to some other button. A typical example is
getting the value of a filename field when the user presses the Load button.
Text item notify procedures are passed the item and the event which caused
notification:
Panel_setting
text_notify__proc (item, event)
Panel_item item;
Event *event;
Writing Your Own Notify
Procedure
The input character is referenced by event_action (event).
Revision A, of May 9,1988
182 SunView 1 Programmer’s Guide
For example, suppose you want to be notified only when the user types I Esc I or
[ Control-01 into an item, but you still want them to be able to move to the next
item, tab, or select
lanuinam
Create the item as shown below.
r
name__item = panel_create_itern (panel, PANEL__TEXT,
P ANEL_LABE L__STR ING,
"Enter Name Here:",
P ANEL_NOT I FY_LE VEL,
PANEL_SPECIFIED,
PANEL_NOT I FY__STRI NG,
"\n\r\t\033\03",
P ANEL_NOT I FY_PROC,
name_proc.
0);
\
_>
Note that you must remember to return the appropriate value from your notify
procedure. The easiest way to do this is to simply call the default text notify pro¬
cedure, and return what it returns:
--
Panel_setting
name_proc(item, event)
Panel_item item;
Event *event;
{
switch (event_action(event)) {
case ' 33': /* user pressed [Esc] */
/* special processing of escape */
return (PANEL__NONE) ;
case ' 03': /* user pressed [Ctrl-C] */
/* special processing of*C */
return (PANEL_NONE) ;
default:
return (panel_text_notify(item, event));
}
}
>- y
Text Value As shown in the example under Displaying Text Items, you can set the value of a
text item at any time via PANEL_VALUE. You can also use the
panel_set_value () macro, as in:
panel_set_value(name_item, "Millard Fillmore");
s___ J
The following call retrieves the value of name_item into name:
---\
Panel_item name_item;
char name [NAME__ITEM_MAX_LENGTH ] ;
strcpy(name, (char *)panel_get_value(name_item));
Note that name_item should have been created with a
PANEL_VALUE_STORED_LENGTH not greater than
NAME ITEM MAX LENGTH, so the buffer name will not overflow.
microsystems
Revision A, of May 9,1988
Chapter 9 — Panels 183
Text Menus
Example
A menu may be associated with a text item by setting PANEL_SHOW_MENU to
TRUE.
One use of text item menus is to make any item-specific “accelerators”, or char¬
acters which cause special behavior, visible to the user. This usage of accelera¬
tors may be seen in Figure 9-5 which is taken from iconedit. The item
labelled File: holds the name of the file being edited. In addition to typing print¬
able characters, which are appended to the value of the item, the user can type
[Esc 1 for filename completion, I Control-L 1 to load an image from the file,
I Control-S I to store an image to the file, or I Control-B I to browse the images in a
directory.
Figure 9-5 A Text Menu
FIle: dervish.image “ Filename completion
. - Load image from file
'S - Store image to file
S B - Browse directory
S Q - Quit
#define ESC 27
♦define CTRLJL 12
♦define CTRL_S 19
♦define CTRL_Q 17
♦define CTRL B 2
panel_create_item(panel, PANEL_TEXT
"File:",
filename_item
PANEL_LABEL_STRING,
PANE L__NOT IF Y_LEVEL,
P ANEL_NOT IF Y_PROC,
PANE L_VALUE_D ISP LAY__LENGTH
PANEL_SHOW_MENU,
PANEL MENU CHOICE STRINGS,
P ANEL__ALL ,
filename_proc,
18,
TRUE,
"ESC - Filename completion"
" ~L - Load image from file
" ~S - Store image to file"
" ~B - Browse Directory",
" ~Q - Quit",
0 ,
PANEL_MENU_CHOICE_VALUES,
0 );
ESC, CTRL_L, CTRL_S,
CTRL_B,CTRL_Q, 0,
The last two attributes specify the menu. PANEL_MENU_CH0ICE_STRINGS is
a null-terminated array of strings to appear as the selectable lines of the menu.
The value that the menu returns for each of its lines is specified via
PANEL_MENU_CHOlCE_VALUES. So if the menu line ‘X - Load image from
file’ is selected, the menu will return the value CTRL_L. The value returned by
the menu is passed directly to the text item, just as if it had been typed at the key¬
board.
Revision A, of May 9, 1988
184 SunView 1 Programmer’s Guide
9.9. Sliders
Displaying Sliders
Slider Selection
Slider Notification
A slider has four displayable components: the label, the current value, the slider
bar, and the minimum and maximum allowable integral values (the range).
When panel_SHOW_value is TRUE, the current value is shown in brackets
after the label. The font used to render the value is PANE L_VALUE_FONT.
The slider bar width in pixels is set with PANEL_SLIDER_WIDTH. 61 The
m inimu m and maximum allowable values are set with PANEL_MIN_VALUE
and PANE L_MAX_VALUE . The width of the slider bar corresponding to the
current value is filled with grey. The slider bar is always displayed, unless the
item is hidden (i.e., PANEL_SHOW_lTEM is FALSE). When
PANEL_SHOW_RANGE is TRUE, the minimum value of the slider
(P ANE L_M IN_VALUE) is shown to the left of the slider bar and the maximum
value (PANEL_MAX_VALUE) is shown to the right of the slider bar.
Only the slider bar of a slider may be selected. When the left mouse button is
pressed within the slider bar or the mouse is dragged into the slider bar with the
left mouse button pressed, the grey shaded area of the bar will advance or retreat
to the position of the cursor. If the mouse is dragged left or right within the
slider bar, the grey area will be updated appropriately. If the cursor is dragged
outside of the slider bar, the original value of the slider (i.e., the value before the
left button was pressed) will be restored.
Slider notify procedures are passed the item, the item’s value at time of
notification, and the event which caused notification:
slider_notify_j?roc(item, value, event)
Panel_item item;
int value;
Event *event;
The notification behavior of a slider is controlled by PANEL_NOTIFY_LEVEL.
When PANEL_NOTlFY_LEVEL is set to PANEL_DONE, the notify procedure
will be called only when the select button is released within the slider bar. When
PANEL_NOTlFY_LEVEL is set to PANEL_ALL, the notify procedure will be
called whenever the value of the slider is changed. This includes:
□ when the select button is first pressed within or dragged into the slider bar,
□ each time the mouse is dragged within the slider bar,
□ when the mouse is dragged outside the slider bar,
□ when the select button is released.
61 If you want to specify the width in characters, use the “column units” macro ATTR_COLS () described in
Chapter 18, Attribute Utilities.
Displaying Sliders
Slider Selection
Slider Notification
Revision A, of May 9, 1988
Chapter 9 — Panels 185
Slider Value The value of a slider is an integer in the range PANEL_MIN_VALUE to
PANE L_max_value . You can retrieve or set a slider’s value with the attribute
PANEL_VALUE.
Example Figure 9-6 illustrates a typical slider, which might be used to control the bright¬
ness of a screen:
Figure 9-6 A Typical Slider
Brightness: [75]
] 100
*
panel_create__item(panel, PANEL_SLIDER,
PANEL_LABEL_STRING,
PANEL_VALUE,
PANE L_MI N__VALUE,
PANE L_MAX_VALUE,
PANEL_SLIDER_WIDTH,
PANEL_NOTIFY_PROC,
"Brightness: ”,
75,
0 ,
100 ,
300,
brightness_j?roc.
0 );
9.10. Painting Panels and To repaint either an individual item or an entire panel, use:
Individual Items , , ^, , ....
panel_paint(panel_ob]ect, paint_behavior)
<Panel_item or Panel> panel_ob ject /
Panel_setting paint_behavior;
paint_behavior should be either PANEL_CLEAR, which causes the rectan¬
gle occupied by the panel or item to be cleared prior to repainting, or
PANEL_NO_CLEAR, which causes repainting to be done without any prior clear¬
ing.
You don’t have to call panel_paint () for items which you create at the same
time as you create the panel — when the panel is initially displayed, each of its
items will be painted. Note, however, that simply creating a panel item does not
cause it to be painted. So items which you create after the panel has been ini¬
tially displayed will not appear until you call panel_paint ( ).
The special attribute PANEL_PAINT is provided to allow you to control the
“repaint behavior” of an item when one of its attributes is set. PANEL_PAINT
has three possible values:
□ PANEL_CLEAR — the item will be automatically cleared and repainted
after each call to panel_set () .
□ PANEL_NO_CLEAR — the item will be automatically repainted (without
any prior clearing) after each panel set () call.
a P ANEL_NONE — no automatic repainting will be done.
The default value for panel_paint is panel_clear. Thus, in the default
case, you do not need to call panel_paint () after calling panel_set ().
^ microsystems
Revision A, of May 9, 1988
186 SunView 1 Programmer’s Guide
You can set the repaint behavior for an item when the item is created, or for all
items in the panel when the panel is created. The item’s repaint behavior may
not be reset after the item is created. However, you may temporarily override an
item’s repaint behavior on any call to panel_set () by giving a different set¬
ting for PANEL_PAINT. The examples which follow show two possible repaint
policies.
Example 1:
-- s
iteml - panel_create_item(panel, PANEL_TEXT,
PANEL_LABEL_STRING, "Enter Name:",
PANEL_VALUE_DISP LAY_LENGTH, 10,
PANEL_PAINT, PANEL_NONE,
0 );
(beginprocessing events, etc...)
panel_set(iteml, PANEL_ITEM_X, 10, PANEL_ITEM_Y, 50, 0);
panel_set(iteml, PANEL_LABEL_IMAGE, Spixrectl, 0);
panel_set(iteml, PANEL_VALUE_DISPLAY_LENGTH, 30, 0);
panel_paint(iteml, PANEL_CLEAR);
v___'
®sun
Xr microsystems
Revision A, of May 9, 1988
Chapter 9 — Panels 187
Example 2:
item2 = panel_create_itern(panel, PANEL__TEXT
PANEL LABEL STRING
"Enter Name:"
PANEL_VALUE_DISP LAY_LENGTH, 10
0 );
(beginprocessing events, etc...)
panel_set(item2
PANEL_ITEM__X, 10,
PANE L__I TEM_Y, 50,
PANEL PAINT, PANEL NONE
0 );
panel_set(item2
PANEL_LABEL_IMAGE, Spixrectl
PANEL PAINT
PANEL NONE
0 );
panel_set(item2
PANEL__VALUE_D I SPLAY_LENGTH, 30
0 );
The above two examples each produce the same effect. In the first example, the
item’s repaint behavior is set to PANEL_NONE at creation time, so it is not
repainted automatically after the panel_set () calls, and no repainting occurs
until the call to panel_paint (). In the second example, the item’s repaint
behavior is the default, PANEL_CLEAR. This is overridden in the first two
panel_set() calls, so no repainting occurs. However, it is not overridden in
the third call to panel_set (), so repainting occurs before that call returns.
As mentioned above, the repaint behavior for all items in a panel can be set when
the panel is created, e.g.:
/-\
window_create (frame, PANEL, PANE L_P AI NT, PANEL_NONE, 0) ;
v_ j
All items created in the above panel will have a repaint behavior of
PANEL NONE.
Revision A, of May 9, 1988
188 SunView 1 Programmer’s Guide
9.11. Iterating Over a
Panel’s Items
You can iterate over each item in a panel with the two attributes
PANEL_FIRST_ITEM and PANEL_NEXT_ITEM. A pair of macros,
panel_each_item () and panel_end_each are also provided for this
purpose. For example, to destroy each item in a panel you would call:
Panel_item item;
panel_each__item (browser, item)
panel_destroy_item(item) ;
panel_end_each
^_ )
NOTE
Parentheses are not required around the statements to be executed on each itera¬
tion. Also, a semicolon is not required after panel_end_each.
9.12. Panel Item Client
Data
One attribute applicable to items of all types which should be mentioned is
P ANEL_CL IENT_D AT A. You can use this attribute in a variety of ways.
Peihaps the most common use is to associate a unique identifier with each item.
This is convenient in the case where you have many items, or where you are
creating and destroying items dynamically. If you need to pick one item out of
all the items, you can store an identifier (or a class) with it via
PANEL CLIENT_DATA, and then query the item directly to find out its
identifier or class.
The detool program in Appendix A, Example Programs, demonstrates this use of
PANEL CLIENT DATA. The panel buttons for its number keys 0-9 share the
same notify procedure. Each button’s PANEL_CLIENT_DATA holds the Ascn
digit displayed on the button; when a button is pushed, the
PANEL CLIENT_DATA is retrieved and displayed on the “screen” of the calcu¬
lator. This saves having a different notify procedure for every button.
You can also use PANEL_CLIENT_DATA to associate a pointer to a private
structure with an item. For one example of this usage, see the example in the
next section under Writing Your Own Event Handler. Another application would
be to link several items together into a list which is completely under your con¬
trol.
Asun Revision A, of May 9,1988
Xr microsystems
Chapter 9 — Panels 189
9.13. Event Handling
Default Event Handling
Writing Your Own Event
Handler
This section describes how the panel package handles events. 62 If you require a
behavior not provided by default, you can write your own event handling pro¬
cedure for either an individual item or the panel as a whole.
Using the default event handling mechanism, events are handled for all the panel
items in a uniform way. A single routine reads the events, updates an internal
state machine, and maps the event to an action to be taken by the item. Actions
fall into two categories: previewing and accepting. The previewing action gives
the user visual feedback indicating what will happen when he releases the mouse
button. The accepting action causes the item’s value to be changed and/or its
notify procedure to be called, with the event passed as the last argument.
The default event-to-action mapping is given in the following table:
Event
Action
Left button down or drag in w/left button down
Begin previewing
Drag with left button down
Update previewing
Drag out of item rectangle with left button down
Cancel preview
Left button up
Accept
Right button down
Display menu & accept user’s selection
Keystroke
Accept keystroke if text item
What actually happens when an item is told to perform one of the above actions
depends on the type of the item. For example, when asked to begin previewing,
a button item inverts its label, a message item does nothing, a slider item redraws
the shaded area of its slider bar, etc. 63
You may want to handle events in a way which is not supported by this default
scheme. For example, there is no way to take any action on middle mouse button
events. To do so you must extend the event handling functionality by replacing
the default event-to-action mapping function for a panel or panel item. Three
attributes have been defined for this purpose:
Table 9-3 Panel Event Handling Attributes
Attribute
Argument Type
Default Value
PANEL_EVENT_PROC
int (*) ()
panel_default_handle_event ()
PANE L_BACKGRO UND_P ROC
int (*) ()
panel__default_handle_event ()
P ANEL_ACCEP T__KEY STROKE
boolean
FALSE
An item’s PANEL_EVENT_PROC is called when an event falls over the item.
The event procedure for an item defaults to that for the panel. Thus you can
change the event procedure for all the items in a panel by specifying your own
PANEL_EVENT_PROC for the panel before the panel items are created. The
arguments passed to the event procedure are the item (or panel) and the event.
62 The general SunView input paradigm, including details on the various events, is covered in Chapter 6,
Handling Input.
63 For particulars, see the Selection subsection under each item type.
microsystems
Revision A, of May 9, 1988
190 SunView 1 Programmer’s Guide
The default event procedure, which implements the default event-to-action map¬
ping described on the previous page, is:
panel_default_handle_event(object, event)
<Panel_itemorPanel> object;
Event *event;
The panel’s PANEL_BACKGROUND_PROC is called when an event falls on the
background of the panel (i.e. an event whose locator position does not fall over
any item). The default panel background procedure is also
panel_def ault_handle_event (); however, the various actions are no-
ops for the panel. Note that this attribute only applies to a panel; it has no mean¬
ing for an individual panel item.
The attribute PANEL_ACCEPT_KEYSTROKE determines whether or not an item
or panel is interested in keystroke events. If this is TRUE, the item or panel
under the cursor is given keystroke events as they are generated. The default
behavior sends all keystroke events to the text item with the caret, independent of
the cursor position.
In addition to the three event related attributes, three event codes have been
defined:
□ p ANEL_EVENT_DRAG_IN — the item or panel was entered for the first
time with one or more buttons down.
□ P ANE L_E VENT_MOVE_IN — the item or panel was entered for the first
time with no mouse buttons down.
□ P ANE L_E VENT_CANCE L — the item or panel is no longer “current” so any
operations in progress should be canceled (e.g. cancel previewing).
The panel package will generate these events as appropriate and pass them to the
item’s event procedure or the panel’s background procedure.
The event-to-action mapping is performed by means of a set of action functions.
If you haven’t specified an event procedure for the item,
panel_default_handle_event () will map events to the appropriate
actions by calling one of the action functions. These action functions have been
made public so that, if you replace the event procedure for an item, you can ask
the panel package to perform one of the default actions by calling the
corresponding action function from your new event procedure.
The action functions are given in the table on the following page.
microsystems
I
Revision A, of May 9, 1988
Chapter 9 — Panels 191
Example
Table 9-4 Panel Action Functions
Definition
Description
panel_accept_key(object, event)
<Panel or Panel Jit em> object;
Event *event;
Tells a text item to accept a keyboard
event. Currently ignored by non-text
panel items.
panel_accept_menu(object, event)
<Panel or Panel_item> object ;
Event *event;
Tells an item to display its menu
and process the user’s selection.
panel_accept_preview(object,
<Panel or Panel Jitem> object;
Event *event;
event)
Tells an item to do what it is supposed
to do when selected, including completing
any previewing feedback.
panel_begin__preview (object,
<Panel or Panel item> object;
Event *event;
event)
Tells an item to begin any feedback
which indicates tentative selection.
pane l_cancel_p re view(object,
<Panel or Panel item> object;
Event *event;
event)
Tells an item to cancel any previewing
feedback.
panel__update_preview (object,
<Panel or Panel Jit em> object;
Event *event;
event)
Tells an item to update its previewing
feedback (e.g. redraw the
slider bar for a slider item).
In most of the action routines, only the event’s location and shift state are of
interest. When previewing, choices, toggles and sliders use the event’s location
to determine the current value. Choices use the shift state to determine whether
to advance or backup the current choice. panel_accept_key () is the only
action function to make use of the actual event code.
Suppose you are implementing dbxtool and want to have the buttons in the com¬
mand panel execute different commands depending on whether they were
selected with the left or middle mouse button. For example, the button labeled
next might behave as the step button if activated with the middle button. When
the middle button is depressed, you want to preview an alternate label, and when
it is released, you want to execute the dbx command corresponding to the pre¬
viewed label.
You can get get this functionality by replacing the event procedure for each of
the button items in the command panel. This could be done either by specifying
a default event procedure for all the items when the panel is created:
f
panel = window_create(frame, PANEL,
PANEL_EVENT_PROC, dbx event proc,
0);
-\
<_
or by specifying a the event procedure as each panel item is created:
r
panel__create_item (panel, PANEL_BUTTON,
PANEL EVENT PROC, dbx event_proc,
0);
Revision A, of May 9,1988
192 SunView 1 Programmer’s Guide
Whenever one of the buttons gets an event, dbx_event_proc () will be
called and can then map the events to actions as it sees fit The code for the new
event procedure is given below. Note the use of PANEL_CLIENT_DATA to
store the images for the two labels for each item.
dbx_event_proc (item, event)
Panel_item item;
Event *event;
{
struct dbx_data *dbx_data; /* data stored with each item */
Panel panel;
/* First get my private data for this item. */
panel = (Panel) panel_get(item, PANEL_PARENT_PANEL) ;
dbx_data = (struct dbx__data *) panel_get (item, PANEL_CLIENT__DATA) ;
/* See if this is an event of interest. */
switch (event__action (event)) {
/* middle button went up or down */
case MS_MIDDLE:
if (event_is_down(event)) {
/* middle button went down, so change the button's label
* image to reflect its middle button action.
*/
panel_set (item, PANEL_LABEL_IMAGE, dbx_data->middle_pr, 0) ;
/* now begin the normal previewing */
panel_begin_preview(item, event);
} else {
/* middle button went up, so accept the previewing */
panel_accept_j?review (item, event) ;
/* now change the image back */
panel_set(item, PANEL_LABEL_IMAGE, dbx_data->left_pr, 0);
}
break;
/* drag into item with button down */
case PANEL_EVENT_DRAG_IN:
if (window_get(panel, WIN_EVENT_STATE, MS_MIDDLE)) {
/* middle button is down, so treat this as begin preview.
*/
panel_set (item, PANEL_LABEL_IMAGE, dbx_data->middle_jpr, 0) ;
panel_begin__preview (item, event) ;
}
else
/* we weren't previewing, so
* let the default event proc handle it.
*/
panel_default_handle_event(item, event);
break;
m sun
Xr microsystems
Revision A, of May 9,1988
Chapter 9 — Panels 193
/* cancel for some reason */
case PANEL_EVENT_CANCEL:
if (panel_get(item, PANEL_JLABEL_IMAGE) ==
dbx_data->middle^pr) {
/* we were previewing — cancel it.
*/
panel_cancel_preview (item, event) ;
panel_set (item, PANEL_LABEL_IMAGE, dbx_data->left_pr, 0) ;
} else
/* we weren't previewing, so
* let the default event proc handle it.
*/
panel_default_handle_event (item, event) ;
break;
/* some other event */
default:
/* we don't care about this event — let the default
* event proc handle it.
*/
panel__default_handle_event (item, event) ;
}
}
The final step is to modify the notify procedure for each button to perform dif¬
ferent actions depending on which mouse button was released. The notify pro¬
cedure for the step/next button, for example, would look like:
r
>
next_step_notify_j>roc (item.
event)
Panel_item item;
t
Event *event;
if (event_action (event)
== MS_MIDDLE)
/* do middle button
command, "step" */
else
}
/* do left button command, "next" */
<
j
Translating Events from In the case of a scrollable panel, the panel is larger than the subwindow in at least
Panel to Window Space one dimension. If the panel has been scrolled, each point within the subwindow
will have one location in the coordinate space of the panel and a different loca¬
tion in the coordinate space of the subwindow. Two functions are provided to
translate event coordinates from panel space to window space, and vice versa.
If you read your own events with window_read_event () , 64 you must
translate the events from window space to panel space with:
64 window_read_event () is described in Chapter 6, Handling Input.
microsystems
Revision A, of May 9, 1988
194 SunView 1 Programmer’s Guide
Event *
panel_event(panel, event)
Panel panel;
Event *event;
To go from panel space to window space, use:
Event *
panel_window_event(panel, event)
Panel panel;
Event *event;
Example
Figure 9-7 illustrates the image browser from iconedit. It serves as an exam¬
ple of when to use panel_window_event (). If the user presses the menu
button over an image, then he gets a menu showing the name of the file contain¬
ing the image:
Figure 9-7 Image Browser Subframe Using panel_window_event ()
In order for the menu to be displayed in the correct place in a panel which has
been scrolled, the menu’s location must be specified in the coordinates of the
subwindow, not of the panel.
XT microsystems
Revision A, of May 9, 1988
Chapter 9 — Panels 195
The browser is implemented as a panel containing buttons having the images as
their labels. The buttons are created each time the user wants to browse a dif¬
ferent set of images. When each button is created, the name of the file containing
the image is stored as the value of the button’s PANEL_CLIENT_DATA.
Listed below is the event procedure shared by each button. There is a global
menu containing a single menu item, image_menu_item. If the event is a
right mouse button, the display string for this menu item is set to the file name
which was previously stored as the button’s PANEL_CLIENT_DATA.
Then the event is adjusted from panel space to window space, and the menu is
displayed at the proper coordinates. If the user selects from the menu, the
button’s notify procedure, browser_items_notif y_proc (), is called, so
the effect is the same whether the item is selected through the menu or directly.
-.
browser__it ems_event_proc (item, event)
Panel_item item;
Event *event;
{
if (event_action(event) == MS_RIGHT) {
Event *adjusted_event;
menu_set (image_menu_item,
MENU_STRING, panel_get (item, PANEL_CLIENT_DATA) , 0) ;
adjusted_event = panel_window_event(browser, event);
if (menu_show(image_menu, browser, adjusted_event, 0)) {
browser_items_notify_proc (item) ;
return;
}
}
panel_default_handle_event (item, event) ;
}
s_>
Note that for all events other than the right mouse button, the panel’s default
event procedure is called.
microsystems
Revision A, of May 9,1988
10
Alerts
Alerts. 199
10.1. Introduction to Alerts. 199
Uses of Alerts. 201
10.2. The Components of an Alert. 201
Alert Arrow. 201
Multiple-Line Text Message. 201
Buttons. 201
Positioning. 202
Beeping. 202
10.3. alert_prompt () ... 202
10.4. Building an Alert. 202
Example 1 — Messages and Simple Buttons. 203
Yes and No Buttons. 204
Example 2 — Changing Fonts. 206
Example 3 — Using Triggers. 206
Alerts
This chapter describes the alerts package, which you can use by including the file
<suntool/alert. h> in your program.
This chapter is divided into three logical sections. Section 1 provides a brief
introduction to alerts. Section 2 explains the components that make up alerts.
Sections 3 gives program fragments that introduce most of the alert attributes.
10.1. Introduction to Alerts An alert is a pop-up frame that contains a panel to notify a user of problems or
changes that require their attention. An alert is easily identified visually by a
large black arrow that sweeps into the alert window from the left. A SunView
application can use alerts to notify a user that an event has taken place or to ver¬
ify that a user requested some action. Each alert that pops up has full screen
access. That is, the screen is frozen until the user responds to the alert.
Alerts are a replacement for the menu_prompt () facility. Some programs will
use menu prompts instead of alerts if the user disables alerts in
def ault sedit. Menu prompts offer a simple box with text, and a maximum
of two choices.
Alerts, on the other hand, have a better user interface. Alerts provide an
attention-getting alert arrow, buttons, fonts, beeps, a 3-D shadow, and so on.
Using alerts, you can offer a user more than two choices of action.
Summary Listing and Tables To give you a feeling for what you can do with alerts, the following page con¬
tains a list of the available alert attributes and functions. Many of these are dis¬
cussed in the rest of this chapter as they occur in the examples and elsewhere
(use the Index to check). All are briefly described with their arguments in the
alert summary tables in Chapter 19, SunView Interface Summary:
□ the Alert Attributes table begins on page 316;
□ the Alert Functions and Macros table begins on page 318;
V microsystems
199
Revision A, of May 9,1988
200 SunView 1 Programmer’s Guide
Alert Attributes
ALERT_BUTTON
ALERT_ME S S AGE_STR I NGS_ARRAY_P TR
ALERT_BUTTON_FONT
ALERT_NO_BEEPING
ALERT_BUTTON_NO
ALERT__OPT IONAL
ALERT_BUTTON_YES
ALERT__P OS ITI ON
ALERT_MESSAGE_FONT
ALERT_P OSITION
ALERT_MESSAGE_STRINGS
ALERT_TRIGGER
Alert Functions
alert_prompt(client_frame, event, attributes)
Xr microsystems
Revision A, of May 9, 1988
Chapter 10 — Alerts 201
Uses of Alerts
A SunView application uses alerts to display messages to the user, who can then
either continue, cancel, or choose a different course of action. Possible uses of
alerts include the following:
□ Querying whether an action was intended: “Are you sure you want to Quit?”
□ Notifying a user of a current state: “Unrecognized file name. No files match
specified pattern.”
10.2. The Components of
an Alert
Figure 10-1 illustrates the visible components that make up an alert. Each com¬
ponent is described below.
Figure 10-1 An Alert
Alert Arrow
Are you sure you want to Cancel window?
. Text Message
[Do NOT cancel window]
Buttons
Alert Arrow
Each alert window is identifiable as an alert by the large black arrow that sweeps
into the window from the left.
Multiple-Line Text Message
Do you really want to exit SunView?
A multiple-line text message describes why an alert appeared and what to do in
order to continue. For example, if the user tries to quit SunView, an alert with
the message, “Do you really want to exit SunView?”, will pop up.
Buttons
[Cancel]
Buttons make it possible to give the user a choice of actions when warning them
that an event has taken place. Each button is associated with a string that
specifies an action.
Many alerts have a default button which is indicated by a double outline (as in
the Confirm button above). If an alert has a default button, then the pointer will
jump to this button when the alert appears, so that clicking LEFT will take the
default action. The pointer is moved back to its original position when the alert
goes away. The user can disable pointer jumping by setting
SunView!Alert Jump Cursor to disabled in def ault sedit.
®sun
\r microsystems
Revision A, of May 9, 1988
202 SunView 1 Programmer’s Guide
Positioning
Beeping
10.3. alert_prompt ()
10.4. Building an Alert
You have three choices for alert placement. The alert may be screen-centered,
client-centered, or client-offset.
An alert may be specified to pop up with or without a beep. The default is to
come up beeping the number of times that is specified in def ault sedit. You
may set your alert to come up without a beep even if the user’s default
SunView!Alert_B ell entry in def ault sedit is to come up beeping.
There is only one function in the alert package, alert_prompt <); it creates
an alert, pops it up on the screen, handles user interaction, then takes down the
alert and returns a value.
int
alert_j?rompt (client_frame, event, attributes)
Frame c 1 ient_f rame ;
Event *event
<attribute-list> attributes;
alert_prompt () displays an alert whose appearance and behavior is
specified by the attribute value list attributes. It does not return a value
until the user pushes a button in the alert or the default trigger event or its
accelerator is seen. By default the alert is positioned over the center of
client_frame.
If you supply a pointer to an event as event, it will be filled in with the user
event which dismissed the alert. For example, if the users pushes a button by
clicking LEFT, event_action (event) will be MS_LEFT. 6 ^
The possible status values which alert_prompt () returns are:
□ ALERT_YES — the user pushed the “yes” alert button
□ ALERT_NO — the user pushed the “no” alert button
□ ALERT_FAILED — the alert_prompt () failed for some reason
□ alert_triggered — a triggered response occurred
□ Some other integer — the user pushed some other button than “yes” or “no.”
This section contains code fragments that illustrate most of the attributes for the
alerts package. For a complete list and explanation of the alert attributes, see
Chapter 19, SunView Interface Summary. Each code fragment described below
is organized as follows:
□ Attributes introduced in the code are described
□ An illustration of the alert box is given
□ The code is listed and described.
65 See Chapter 6, Handling Input for an explanation of the Events.
®sun
Xr microsystems
Revision A, of May 9, 1988
Chapter 10 — Alerts 203
For a complete program example using alerts, see filer in Appendix A, Example
Programs.
Example 1 — Messages and This section gives two code fragments in order to illustrate the different button
Simple Buttons attributes. The buttons allow the user to choose an action. Each alert may contain
one or more buttons; the default is for no buttons.
Each button has a name and an associated value. When a user pushes a button,
the value associated with the button is returned.
The following attributes are used in the first code fragment. STRINGS""
ALERT_MESSAGE_STRINGS
The ALERT_MESSAGE_STRINGS attribute specifies a string or strings to be
displayed in the message area of the alert panel.
An example of the syntax for a message is:
ALERT_ME S SAGE_STRINGS,
"The text has been edited.",
"Empty Document will discard these edits. Please confirm",
0 ,
The ALERT_BUTTON attribute displays a string in a button and associates a
value to it. The value specified with the string is returned when the button is
pushed. The value may be any integer, but should not be one of the values
predefined by the alerts package ( ALERT_YES, alert_NO, ALERT_FAILED,
or ALERT_TRIGGERED ). Figure 10-2 illustrates an alert that was built using
the attributes ALERT BUTTON. It contains four buttons and one text string.
This example asks the user what part of the country they are from. The program
fragment is listed below.
Figure 10-2 A Simple Alert
result = alert_prompt(
(Frame) client_frame,
(Event*) NULL
ALERT_ME S SAGE_S TRINGS
"What part of the country are you from?",
0 ,
ALERT_BUTTON,
"North",
101,
ALERT_BUTTON,
"East",
102,
ALERT_BUTTON,
"West",
103,
ALERT_BUTTON,
"South",
104,
sun
microsystems
Revision A, of May 9,1988
204 SunView 1 Programmer’s Guide
Yes and No Buttons
switch (result) {
case 101:
/^handle
case
for
someone
from
the
North*/
break;
case 102:
/*handle
case
for
someone
from
the
East*/
break;
case 103:
/^handle
case
for
someone
from
the
West*/
break;
case 104:
/*handle
case
for
someone
from
the
South*/
break;
case ALERT_
FAILED:
/*
* Possibly out of memory or fds;
* attempt to get information another way
*/
break;
Usually you will want to map your buttons to “yes” and “no” actions. To make
this possible, two special buttons are triggered by predefined keyboard accelera¬
tors. Yes (confirm, do it) is mapped to the I Return I key. No (cancel, don’t do it)
is mapped to the I Stop 1 key (usually [ LI 1 ).
The SunView event name for yes is ACTI0N_D0_IT. The SunView event
name for no is ACT I0N_ST0P.
The following attributes are used in this example:
The ALERT_BUTTON_YES attribute associates a string with the accelerated
YES button. The value ALERT_YES is returned by alert_prompt () if the
user pushes this button, or types I Return 1 . Only one instance of this attribute is
allowed; subsequent instances are ignored.
The YES button image will have a different button image than the other buttons.
It will appear as a regular button image with a double outline.
An example of the syntax is:
ALERT_BUTTON_YES, "Confirm, discard edits".
The alert_button_no attribute associates a string with the accelerated NO
button. The value returned if the user pushes this button, or types I Stop I , will be
ALERT_NO. Only one instance of this attribute is allowed; subsequent instances
are ignored.
microsystems
Revision A, of May 9,1988
Chapter 10 — Alerts 205
An example of the syntax is:
ALERT_BUTTON_NO, "Cancel",
Figure 10-3 illustrates the alert that is generated by the following code. It con¬
tains two buttons and two text strings. The buttons give the user two choices: to
empty a document, discarding any edits they may have made, or to cancel the
operation completely.
Figure 10-3 A YES/NO Alert
The text has been edited.
Empty Document will discard these edits. Please confirm.
int result;
result = alert_prompt(
(Frame)window,(Event*)NULL,
ALERT__ME S SAGE_STR INGS,
"The text has been edited.",
"Empty Document will discard these edits.\
Please confirm.",
0 ,
ALERT_BUTTON_YES, "Confirm, discard edits",
ALERT_BUTTON_NO, "Cancel",
0 );
switch(result){
case ALERT_YES:
/*discard edits*/
break;
case ALERT_NO:
/♦cancel the Empty Document request */
break;
case ALERT_FAILED:
break;
Revision A, of May 9, 1988
206 SunView 1 Programmer’s Guide
Example 2 — Changing Fonts The default font used for alert message text is the Client Frame’s font, if one has
been specified; or else it is the same as SunView/Font. The default font for alert
buttons is the same as that specified for menus in Menus/Font in defaultsedit, or
screen.b.14, if no default is specified.
You may prefer to use different fonts within alerts. For example, you might want
to set off the text in an alert box from the text in the Client’s frame by using the
bold version of the Client Frame’s default font.
The ALERT_MESSAGE_FONT and ALERT_BUTTON_FONT attributes con¬
trol the font setting for the alert message text and alert buttons, respectively.
Figure 10-4 illustrates an alert in which the message string is printed in
courier.b.16. The code fragment shown below it illustrates how to set the
attribute’s value using the font library. It also illustrates the use of multiple mes¬
sage strings.
Figure 10-4 An Alert with Boldface Message Strings
Example 3 — Using Triggers Often you will want to give the user the choice of using mouse buttons or key¬
board accelerators instead of push buttons to respond to an alert. Triggers give
you this option by making it possible to specify an accelerator or mouse action
for a choice.
For example, the text window uses an alert to ask the user where to split a win¬
dow. A left mouse button click is the trigger that responds to this alert.
m sun
Xr microsystems
Revision A, of May 9, 1988
Chapter 10 — Alerts 207
The following attribute is used when specifying a trigger:
The ALERT_TRIGGER attribute allows the application to specify a SunView
event which should cause the alert to return. The default is not to return a value
unless a button has been pushed or the other YES/NO accelerators are seen.
When an event is triggered, the value returned will be ALERT_TRIGGER. An
example of the message syntax is as follows.
ALERTJTRIGGER, event.
Figure 10-5 illustrates the alert that is generated by the following code. This alert
contains one button and a triggered response. When this alert comes up, the user
may split the existing window into two windows, or can dismiss the alert by
pushing the Cancel New Window button. This example also shows how alerts
can effectively use an event to collect information about the way a user reacted to
an alert. See Chapter 6, Handling Input, for a full explanation and list of all pos¬
sible events.
Figure 10-5 An Alert Using Triggers and Events
Move pointer to where new view should
begin, then click the left mouse button.
Otherwise, push "Cancel Split View".
[Cancel Split View]
Revision A, of May 9,1988
208 SunView 1 Programmer’s Guide
----
Event event;
int result;
result = alert_prompt(
(Frame)window,
&event,
ALERT_NO_BEEPING, 1,
ALERT_MESSAGE_STRINGS,
"Move pointer to where new window should",
"appear, then click the left mouse button.",
"Otherwise, push \"Cancel New Window."\,
0 ,
ALERT_BUTT0N_N0, "Cancel New Window",
ALERTJTRIGGER, MS_LEFT,
0 );
switch (result) {
case ALERT_TRIGGERED:
(void) create_new_window_at_pos(event_x(Sevent),
event_y(&event)),
break;
case ALERT__N0:
break; /* don't create new window */
case ALERT_FAILED:
/* alert failed, possibly out of memory or fds */
}
v_ /
You may specify in your code to have an alert pop up without a beep as shown
above. Generally, beeping is reserved for any event which occurs unexpectedly.
If the alert is in response to a user request, it should not beep.
The following attribute is used to specify no beeping for an alert.
The ALERT_NO_BEEP ING attribute allows the SunView application to specify
that no beeping should take place regardless of def aultsedit setting. The
default for this option is FALSE; that is, beep as many times as the defaults data¬
base specifies.
microsystems
Revision A, of May 9, 1988
TTY Subwindows
TTY Subwindows... 211
11.1. Creating a TTY Sub window. 213
11.2. Driving a TTY Subwindow. 213
ttysw_input() . 213
ttysw_input() . 214
Example: tty jo . 214
11.3. TTY Subwindow Escape Sequences. 214
Standard ANSI Escape Sequences. 214
Special Escape Sequences. 215
Example: tty jo . 215
11.4. Reading and Writing to a TTY Subwindow. 215
11.5. The Program in the TTY Subwindow. 215
TTY_PID. 215
Talking Directly to the TTY Sub window. 216
An Example. 216
TTY Subwindows
The tty (or terminal emulator) subwindow emulates a standard Sun terminal, the
principal difference being that the row and column dimensions of a tty subwin¬
dow can vary. You can run arbitrary programs in a tty subwindow; perhaps its
main use is to run a shell within a window.
To see tty subwindows in use, run the standard tools shelltool(l) and
gfxtool(l).
Header Files Programs using tty subwindows must include the file <suntool/tty. h>.
Summary Listing and Tables To give you a feeling for what you can do with tty subwindows, the following
page contains lists of the available tty subwindow attributes, functions and mac¬
ros. Many of these are discussed in the rest of this chapter and elsewhere (use the
Index to check). All are briefly described with their arguments in the tty subwin¬
dow summary tables in Chapter 19, SunView Interface Summary :
□ the TTY Subwindow Attributes table begins on page 376;
□ the TTY Subwindow Functions table begins on page 376;
□ the TTY Subwindow Special Escape Sequences table begins on page 377.
microsystems
211
Revision A, of May 9,1988
212 SunView 1 Programmer’s Guide
TTY Subwindow Attributes
TTY_ARGV TTY_PAGE_MODE
TTY CONSOLE TTY QUIT ON CHILD DEATH
TTY Subwindow Functions
ttysw_input (tty, buf, len) _ ttysw_output (tty, buf, len)
Revision A, of May 9, 1988
Chapter 11 — TTY Subwindows 213
11.1. Creating a TTY
Subwindow
11.2. Driving a TTY
Subwindow
ttysw_input()
Like all SunView windows, you create a tty subwindow by calling
window_create () with the appropriate type parameter, as in:
/—
Tty tty;
tty = window^create(frame, TTY, 0);
V.
J
By default, the tty subwindow will fork a shell. If you want to start the tty
subwindow with another program, say vi, you can do so by specifying the name
of the program to run via the TTY_ARGV attribute:
r~ -\
♦include <suntool/sunview.h>
♦include <suntool/tty.h>
char *my_argv[] = { "vi", 0 };
main ()
{
Tty tty;
Frame frame;
frame = window_create(0, FRAME, 0) ;
tty = window_create(frame, TTY, TTY_ARGV, my_argv, 0) ;
window_main_loop(frame);
}
v_ >
NOTE You can only have one tty subwindow per process.
You can drive the terminal emulator programmatically. There are procedures
both to send input to the terminal emulator (as if the user had typed it in the tty
subwindow) and to send output (as if a program running in the tty subwindow
had output it). The two effects are similar to the mapi / mapo functions in
' / . ttyswr c that permit a user to bind a character sequence to a function
key. 66
You can send input to a tty subwindow programmatically with the function:
int
ttysw_input(tty, buf, len)
Tty tty;
char *buf;
int len;
ttysw__input () appends the character sequence in buf that is len charac¬
ters long onto tty’s input queue. It returns the number of characters accepted.
The characters are treated as if they were typed from the keyboard.
ttysw_input () provides a simple way for a window program to send input to
a program running in its ttysubwindow.
66 See shelltool(l) in the SunOS Reference Manual.
microsystems
Revision A, of May 9, 1988
214 SunView 1 Programmer’s Guide
ttysw_input()
Example: tty Jo
11.3. TTY Subwindow
Escape Sequences
Standard ANSI Escape
Sequences
Use ttysw output () to output to a tty subwindow,
int
ttysw_output(tty, buf, len)
Tty tty;
char *buf;
int len;
tt ysw_output () runs the character sequence in buf that is len characters
long through the terminal emulator of tty. It returns the number of characters
accepted. The effect is similar to executing
—'—~— --- - ——'— - —— - - -— ‘ '
echo character_sequehce > /dev/ttyN
where ttyN is the pseudo-tty associated with the tty subwindow. One use of
ttysw_output () is to send the escape sequences listed in the next section to
the tty subwindow.
Appendix A, Example Programs, gives the listing for tty Jo, a program which
uses tty_output () to output strings of characters to a tty subwindow.
The tty subwindow accepts the same ANSI escape sequences as the raw Sun con¬
sole, 67 with the following few exceptions:
□ The effect of the bell control character CTRL-G (0x07) in a tty subwindow
depends on how the user has set the two options Audible_Bell and
Visible Bell in the SunView category in def ault sedit(l). If
Audible Bell is Enabled, the bell will ring. If Visible Bell is Enabled, the
window will flash.
□ The graphics rendition sequences ESC [ 4m (underline) and ESC [ lm (bold
“extra-bright”) operate correctly. On the Sun console, these sequence
always invert subsequent characters, whereas the tty subwindow only inverts
when sent ESC [ 7m (stand-out).
□ The effect of the bold “extra-bright” graphics rendition sequence ESC [ lm in
a tty subwindow depends on the user’s setting for the Boldstyle option in
the Tty category of def ault sedit.
□ Unsupported graphics rendition mode escape sequences have the same effect
as that chosen for bold “extra-bright”. On the Sun console, everything
inverts.
□ The Set Scrolling sequence ESC [ 0r, which enables vertical wrap mode on
the Sun terminal, has no effect in a tty subwindow.
61 See the conso le(4s) manual page in the SunOS Reference Manual for a full list of escape sequences.
microsystems
Revision A, of May 9,1988
Chapter 11 — TTY Subwindows 215
□ You can modify termcap (5) if you need further control over what gets
displayed in the different modes. The two-character termcap symbols for
each of the modes are:
so standout
us underline
md bold (extra bright)
Special Escape Sequences Escape sequences have been defined by which the user can get and set attributes
of both the tty subwindow and the frame which contains it For example, the
user can type an escape sequence to open, close, move or resize the frame,
change the label of the frame or the frame’s icon, etc. These escape sequences
are described in Table 19-33, TTY Subwindow Special Escape Sequences , in
Chapter 19, SunView Interface Summary.
Example: tty Jo For an example of setting the frame’s label via a tty subwindow escape sequence,
see the program tty Jo, listed in Appendix A, Example Programs.
11.4. Reading and Writing You cannot use the tty subwindow’s file descriptor returned by win_fd to read
to a TTY Subwindow and write characters to it. You can use TTY_TTY_FD attribute to get the file
descriptor of the pseudo-tty associated with the tty subwindow. You can then
use this to read and write to the pseudo-tty using standard UNIX I/O routines.
Note that TTY_TTY_FD is the file descriptor of the pseudo-tty, not the file
descriptor of the tty subwindow returned by WIN_FD. The latter is used for
low-level window manipulation procedures.
11.5. The Program in the
TTY Subwindow
You use the TTY_ARGV attribute to pass the name of the program to run to the
tty subwindow. The program runs as a forked child in the tty subwindow.
TTY_P ID You can use TTY_P ID to monitor the state of the child process running in the tty
window via the Notifier using L notify_interpose_wait3_func() • The client’s
wait 3 () function gets called when the state of the process in the tty subwin¬
dow changes. The setup is something like this:
r
#include <sys/wait.h>
static Notify__value my_wait3();
ttysw = window_create(base_frame,
TTY,
TTY__QU I T_ON_CH I LD_DEATH,
FALSE,
TTY ARGV,
my_argv.
0);
- child_j?id = (int) window_get (ttysw.
TTY_PID);
notify_interpose_wait3_func(ttysw.
my_wait3, child_pid);
Vs
j
The wait3 () function can then do something useful, such as destroying the
tty window or starting up another process in the tty subwindow. Here is a code
fragment that detects the death of its tty subwindow’s child. It turns off the
default behavior of a tty subwindow, which is to quit when the child process dies.
Revision A, of May 9, 1988
216 SunView 1 Programmer’s Guide
static Notify_value
my_wait3(ttysw, pid, status, rusage)
Tty ttysw;
int pid;
union wait *status;
struct rusage *rusage;
{
int child_j?id;
notify_next_wait3_func(ttysw, pid, status, rusage);
if (! (WIFSTOPPED(*status))) {
window_set(ttysw,
TTY_QUI T_ON_CH I LD_DE ATH, FALSE,
TTY__ARGV, my_a r gv,
0 );
child_pid = (int)window_get(ttysw, TTY_PID);
notify_interpose_wait3_func(ttysw, my_wait3, child__pid) ;
}
return NOTIFY_DONE;
)
You can set TTY_PID as well as get it, but if you set it then you are responsible
for setting the notif y_interpose_wait3_f unc () to catch the child’s
death, and for making the standard input and standard output of the child go to
the pseudo-tty.
Talking Directly to the TTY If you set TTY_ARGV to TTY_ARGV_DO_NOT_FORK, this tells the system not
Subwindow to folk a child in the tty subwindow. In combination with TTY_FD, this allows
the tool to use standard I/O routines to read and write to the tty subwindow. 68
This simplifies porting terminal-oriented graphics programs, which interact with
the user on the model of write a prompt ... read a reply , to SunView. However,
in most cases you should redesign programs to use a real windowing interface
made up of SunView components.
An Example The typein program in Appendix A, Example Programs reads and writes directly
to its tty subwindow, using SunView’s window_main_loop () control struc¬
ture.
The following example preserves the flow of control of a typical UNIX applica¬
tion, using notif y_do_dispatch () to ensure that the Notifier gets called.
Read Section 17.6, Porting Programs to SunView, for more information on using
the Notifier in this way.
♦define BUFSIZE 1000
static int my_done;
static Notify_value
my_notice_destroy(frame, status)
Frame frame;
Destroy_status status;
68 This capability makes obsolete the work-around required
in the 3.0 and 3.2 releases of SunView if you
m sun
XT microsystems
Revision A, of May 9, 1988
Chapter 11 — TTY Subwindows 217
if (status != DESTROY_CHECKING) {
my_done = 1 ;
(void)notify_stop();
}
return (not ify_next_destroy_func (frame, status));
}
main(argc, argv)
int argc;
char *argv[];
{
Frame ba s e_f ra me;
Tty ttysw;
int tty_fd;
char buf[BUFSIZE];
my_done = 0;
base_frame = window_create (NULL, FRAME,
FRAME_ARGC_PTR_ARGV, & a rgc, argv,
0 );
ttysw = window_create (base_frame, TTYSW,
TTY_ARGV, TTY_ARGV_DO_NOT_FORK,
0 );
tty__fd = (int) window_get (ttysw, TTY_TTY_FD);
dup2 (tty_fd, 0);
dup2(tty_fd, 1);
(void) notify_interpose__destroy_func (base_frame, my_notice_destroy);
window_set (base__frame, WIN_SHOW, TRUE, 0) ;
(void) notify__do_dispatch () ;
puts (promptJo user) ;
while (gets(buf)) {
if (my_done) /* continue until destroyed */
break;
/*
* This is where the meat of the program
* would be if this were a real program.
*/
puts (buf);
}
exit(0);
wanted a window program to read and write from its own tty subwindow.
microsystems
Revision A, of May 9, 1988
WMMMM
Menus
Menus... 221
12.1. Basic Menu Usage. 224
12.2. Components of Menus & Menu Items. 228
Menus. 228
Visual Components. 228
Generate Procedures. 228
Notify Procedures. 228
Client Data. 228
Menu Items. 228
Menu Items. 228
Representation on the Screen. 228
Item Values. 229
Item Generate Procedures. 229
Item Action Procedures. 229
Client Data. 229
Item Margins. 230
12.3. Examples. 230
12.4. Item Creation Attributes. 237
12.5. Destroying Menus. 238
12.6. Searching for a Menu Item. 239
12.7. Callback Procedures. 240
Flow of Control in menu_show () . 240
Generate Procedures. 242
Menu Item Generate Procedure. 243
Menu Generate Procedure. 244
Pull-right Generate Procedure. 246
Notify/Action Procedures . 247
12.8. Interaction with Previously Defined SunView Menus. 248
Using an Existing Menu as a Pull-right. 248
12.9. Initial and Default Selections. 249
12.10. User Customizable Attributes. 250
12
liiiililllll
Menus
The SunView menu package allows you to chain individual menus together into
a collection known as a walking menu. A menu contains menu items, some of
which may have a small arrow pointing to the right. This indicates to the user
that if he or she slides the mouse to the right of that item, a pull-right menu will
appear. Menus can be strung together in this fashion, so that the user “walks” to
the right down the chain of menus in order to make a selection.
The definitions necessary to use walking menus are found in the file
<suntool/walkmenu. h>, which is included by default when you include
the file <suntool/sunview ,h>.
The most useful sections to read first are the first three. Section 12.1, Basic
Menu Usage, introduces the basic routines and gives some simple examples.
Section 12.2, Components of Menus & Menu Items, outlines the components of
menus and menu items and introduces common terms. Section 12.3, Examples,
gives more examples of using menus. Section 12.7, Callback Procedures, is for
advanced users who need to understand the subtleties of the callback mechanism.
The listing for font menu, a program which builds on some of the examples
given throughout the chapter, is given in Appendix A, Example Programs.
Summary Listing and Tables To give you a feeling for what you can do with menus, the following two pages
list the available menu attributes, functions and macros. Many of these are dis¬
cussed in the rest of this chapter and elsewhere (use the Index to check). All are
briefly described with their arguments in the menu summary tables in Chapter
19, SunView Interface Summary:
□ the Menu Attributes table begins on page 335;
□ the Menu Item Attributes table begins on page 339;
□ the Menu Functions table begins on page 341.
microsystems
221
Revision A, of May 9,1988
222 SunView 1 Programmer’s Guide
Menu Attributes
MENU_ACTION_IMAGE
MENU_LAST_EVENT
MENU_ACTION_ITEM
MENU_LEFT_MARGIN
MENU_APPEND_ITEM
MENU_MARGIN
MENU_BOXED
MENU_NCOLS
MENU_CENTER
MENU_NITEMS
MENU_CLIENT_DATA
MENU_NROWS
MENU__COLUMN_MAJOR
MEN U__NOT IF Y__P ROC
MENU_CLIENT__DATA
MENU_NTH_ITEM
MENU_DESCEND_FIRST
MENU_PARENT
MENU_DEFAULT
MENU_P ULLRI GHT_DELTA
MENU_DEFAULT_I TEM
MENU_PULLRIGHT_IMAGE
MENU_DEFAULT_SELECTION
MENU_P ULLRI GHT_I TEM
MENU_F I RST_EVENT
MENU_REMOVE
MENU_FONT
MENU_REMOVE_ITEM
MENU_GEN_PROC
MEN U_RE P LACE
MENU_GEN__P ULLRI GHT_I MAGE
MENU_REP LACE__I TEM
MENU_GEN_PULLRIGHT_ITEM
MENU_RIGHT_MARGIN
MENU_IMAGE_ITEM
MENU_SELECTED
MENU_IMAGES
MENU_SELECTED__I TEM
MENU_INITIAL_SELECTION
MEN U_SH AD OW
MENUJE NITIAL_SELECTION_EXPANDED
MENU_STAY_UP
MENU_I NITI AL_SELECT I ON__SELECTED
MENU_STRINGS
MENU_INSERT
MENU__STRI NG_I TEM
MENU_INSERT__ITEM
MENU_TITLE_IMAGE
MENU_ITEM
MENU_TITLE_ITEM
MENU_JUMP_AFTER_NO_SELECTI ON
MENU_TYPE
MENU_JUMP_AFTER_SELECTION
MENU_VALID_RESULT
Menu Item Attributes
MENU_ACTION_IMAGEt
MENU_INACTIVE
MENU_ACTION_ITEMf
MENU_INVERT
MENU_ACTION_PROC
MENU_LEFT_MARGINt
MENU_APPEND_ITEMf
MENU_MARGINt
MENU_BOXEDf
MENO_PARENTf
MENU_CENTERf
MENU_PULLRIGHT
MENU_CLIENT_DATAt
MENU_P ULLRIGHT_IMAGEf
MENU_FEEDBACK
MENU_P ULLRIGHT_ITEMf
MENU_FONTf
MENU_RELEASE
MENU_GEN_PROC|
MENU_RELEASE_IMAGE
MENU_GEN_PROC_IMAGE
MENU_RIGHT_MARGINf
MENU_GEN_PROC_ITEM
MENU_SELECTEDf
MENU_GEN_PULLRIGHT
MENU_STRINGf
MENU_GEN_PULLRIGHT_IMAGEf
MENU_STRING_ITEMf
MENU_GEN_PULLRIGHT_ITEMf
MENU_TYPEf
MENU_IMAGE
MENU_VALUE
MENU_IMAGE_ITEMf
Revision A, of May 9, 1988
Chapter 12 — Menus 223
_ Menu Functions _
menu_create(attributes)
menu_creat e__item (attributes)
menu_destroy (menu__ob ject)
menu_destroy__with_proc (menu_ob ject, destroy_proc)
void (*destroy_j?roc) () ;
menu_find(menu, att ributes)
menu_set(menu_object, attributes)
menu_show(menu, window, event, 0)
menu_return_item (menu, menu_item)
menu return_value (menu, menu_item)
microsystems
Revision A, of May 9 S 1988
224 SunView 1 Programmer’s Guide
12.1. Basic Menu Usage The basic usage of menus is to first create the menu with menu_creat e (),
then display it when desired with menu_show ():
Menu
menu_create(attributes)
<attribute-list> attributes;
caddr_t
menu_show(menu, window, event, 0)
Menu menu;
Window window;
Event *event;
Like the creation routines for other SunView objects, menu_create () takes a
null-terminated attribute list and returns an opaque handle, menu show ()
displays the menu, gets a selection from the user, and, by default, returns the
value of the menu item the user has selected, window is the handle of the win¬
dow over which the menu is displayed; event 69 is the event which causes the
menu to come up. The final argument is provided so that attributes may be
passed in the future; at present it is ignored.
Use the routines menu_set () and menu_get () to modify and retrieve the
values of attributes for both menus and menu items:
int
menu_set(menu_object, attributes)
<Menu or Menujtem> menu_ob ject;
<attribute-list> attributes ;
caddr_t
menu_get(menu_object, attribute[, optional_arg])
<Menu or Menu_item> menu_ob ject;
Menu_attribute attribute;
caddr_t optional_arg;
All the attributes applying to menus and menu items are listed in the two
corresponding tables Menu Attributes and Menu Item Attributes in in Chapter 19,
SunView Interface Summary. Common attributes applying to both menus and
menu items appear in both tables.
The pages which follow contain three examples of basic menu usage.
69 Canvases and panels have their own coordinate spaces separate from the window’s coordinate space.
Note that event is in the coordinate space of the window, not of the canvas or panel.
microsystems
Revision A, of May 9,1988
Chapter 12 — Menus 225
Let’s take a very simple example — a menu with two selectable items
represented by the strings ‘On’ and ‘Off:
-
on_off_menu = menu_create(MENU_STRINGS, "On", "Off", 0,
0 ); "
V_
The attribute MENU_STRINGS takes a list of strings and creates an item for each
string. Note that the first zero in the above call terminates the list of strings, and
the second zero terminates the entire attribute list.
CAUTION The menu package, in contrast to the panel package, does not save strings
which you pass in. So you should either pass in the address of a constant, as in
the example above, or static storage, or storage which you have dynamically allo¬
cated.
Typically you call menu_show () from an event procedure, 70 upon receiving
the event which is to cause display of the menu. In the code fragment below, we
display the menu on right button down:
/—
case MS_RIGHT:
>
menu_show(on_of f_menu, window, event, 0);
break;
V
j
menu_show (), by default, returns the value of the item which was selected. If
the item was created with MENU STRINGS its value defaults to its ordinal posi¬
tion in the menu, starting with 17 1 So in the above example, selecting ‘On’
would cause 1 to be returned, while selecting ‘Off would cause 2 to be returned.
You can specify that menu_show () return the item itself, rather than return the
value of the selected item. Do this by setting MENU_NOTlFY_PROC to the
predefined notify procedure 72 menu_return_item (), as in:
—
menu_set (on_of f_menu,
MENU_NOTIFY_PROC, menu_return_item,
0 ); "
V_>
Example 1:
70 See Chapter 6, Handling Input , for a discussion of event procedures.
71 The value of menu items not created with MENU_STRINGS defaults to zero. You can explicitly specify
the values for menu items via the attributes MENU_IMAGE_ITEM, MENU_STRING_ITE M, or MENU_VALUE.
72 Notify procedures are covered in detail in Section 12.7, Callback Procedures.
Revision A, of May 9,1988
226 Sun View 1 Programmer’s Guide
Example 2: It’s easy to build up more complex menus out of simple ones. The next example
creates a menu with two items, ‘Bold’ and ‘Italic’, each of which shares the on-
off menu from the previous example as a pull-right:
r
menu = menu_create (MENU__ITEM,
MENU_STRING,
"Bold",
MENU PULLRIGHT,
on_of f_menu.
0,
MENU_ITEM,
MENU_STRING f
"Italic",
MENU PULLRIGHT,
on_off_menu,
0,
0),
<
The most flexible way to create a menu item in-line in a menu_create () call
is by using MENU_ITEM. In contrast to MENU_STRINGS, which allows you to
specify only the display strings of the items, MENU_ITEM takes as its value a
null-terminated attribute list which may contain any attributes applying to menu
items . 73
The value of MENU_STRING is the item’s display string; the value of
menu_PULLRIGHT is the handle of the item’s pull-right menu. (Note that you
must already have created the menu before giving it as the value for
MENU_PULLRIGHT.)
Example 3: The menu package can accommodate images as well as strings. The example
below creates a menu with a single item labelled ‘tools’. When the user pulls
right, he brings up a menu showing the icons of three SunView tools —
defaultsedit,iconedit, and fontedit.
73 For a complete list of such attributes, see the Menu Item Attributes table in in Chapter 19, SunView
Interface Summary.
#sun
Xr microsystems
Revision A, of May 9, 1988
Chapter 12 — Menus 227
In order to pass an image into the menu package you need a pointer to a memory
pixrect containing the image. One common way to create such an image is by
first using iconedit to create the image and save it to a file. You then include the
file in your program, and use the mpr_stat ic () macro to create a memory
pixrect:
-— >
static short d_defaults[] = {
♦include <images/defaultsedit.icon>
};
mpr_s t at ic (default s_pr, 64, 64, 1, d__defaults);
static short d_icon[] = {
♦include Cimages/iconedit.icon>
};
mpr_static (icon_pr, 64, 64, 1, d_icon);
static short d_font[] = {
♦include <images/fontedit.icon>
};
mpr_static(font^pr, 64, 64, 1, d_font);
tool_menu = menu_create(MENU_IMAGES,
&default s_j?r, &icon_pr, &font_pr, 0,
0 );
menu = menu_create (MENU_ITEM,
MENU_STRING, "tools”,
MENU_PULLRIGHT, tool_menu,
0 ,
0 );
s_ )
The attribute MENU_IMAGES is analogous to MENU_STRINGS. It takes a list of
images (pointers to pixrects) and creates a menu item for each image.
microsystems
Revision A, of May 9,1988
228 SimView 1 Programmer’s Guide
12.2. Components of
Menus & Menu Items
Menus
Visual Components
Generate Procedures
Notify Procedures
Client Data
Menu Items
CAUTION
Menu Items
Representation on the Screen
This section gives an overview of the most important components of menus and
menu items. Detailed discussion and examples follow later in the chapter.
The text for a menu is rendered in the menu’s font, which you may specify via
MENU_FONT. A menu has a shadow, you can specify the shadow’s pattern, or
disable the shadow entirely, via MENU_SHADOW. You can give a title to a menu
via MENU_TITLE_IMAGE or MENU_TITLE_ITEM . 74 By default, a menu’s
items are laid out vertically; you can specify that the items be laid out horizon¬
tally or in a two-dimensional matrix via MENU_NCOLS and MENU_NROWS.
You may specify a generate procedure for a menu, which will be called just
before the menu is displayed. This allows you to implement context-sensitive
menus by dynamically modifying the menu, or even replacing it entirely. 75
The menu’s notify procedure is called after the user makes a selection. By using
a notify procedure, you can perform an action or alter the resultor alter the result
to be returned by menu_show () 76 .
The menu’s client data field, accessible through MENU_CLIENT_DATA, is
reserved for the application’s use. You can use this attribute to associate a
unique identifier, or a pointer to a private structure, with a menu.
A menu contains an array of items. To retrieve a menu’s nth item, use
MENU_NTH_ITEM. To retrieve the total number of items in a menu use
MENU_NITEMS.
The same menu item can appear in more than one menu.
Menu items, unlike panel items, are counted starting with one.
A menu item is either displayed as a string or an image (a pointer to a pixrect). If
the item has another menu associated with it using the MENU_PULLRIGHT attri¬
bute, then it is a pull-right item.
74 The title is nothing more than an inverted, non-selectable item. It does not automatically appear at the top
of the menu — it is your responsibility to position it where you want it.
75 See example 8 in Section 12.7, Callback Procedures , later in the chapter.
76 Notify procedures are discussed in detail in Section 12.7, Callback Procedures.
#sun
xr microsystems
Revision A, of May 9, 1988
Chapter 12 — Menus 229
Item Values
Item Generate Procedures
Item Action Procedures
Client Data
Each menu item has a value. By default an item’s value is the initial ordinal
position of the item if it was created with MENU_STRINGS; otherwise the
default value is zero. You can set an item’s value explicitly when you create the
item with MENU_STRING_ITEM or MENU_IMAGE_ITEM. You can also expli¬
citly set an item’s value with MENU_VALUE. However, if an item is a pull-right,
then its MENU_VALUE is the value of its pull-right menu. This means that only
“leaf’ menu items without submenus have a true value.
As mentioned in Section 12.1, Basic Menu Usage, menu_show () by default
returns the value of the item the user has selected. Since menu items are counted
starting from one, a return value of zero from menu_show () would represent
the null selection. 77 However, you may explicitly set the value of a menu item to
zero. If you do, then a return value of zero could represent either a legal value
for the selected item or an error. To tell whether or not the result was valid, call
menu_get () with the boolean MENU_VALID_RESULT. A return value of
TRUE means that the result was valid; FALSE means that the value is invalid.
As with the menu as a whole, you may specify a generate procedure for each
menu item, to be called just before the item is displayed.
The action procedure of a menu item is analogous to the notify procedure of a
menu. This is your chance to do something immediately based on the user’s
selection.
Menu notify procedures and item action procedures differ in when they are
called. If the user chooses an item in a pull-right menu, the notify procedures (if
any) for the menus higher up in the chain leading to the pull-right will be called,
whereas the action procedures (if any) for the chosen menu item and menu items
under it (“to its right”) will be called. 78
Each menu item has a client data field, accessible through
MENU_CLIENT_DATA, which is reserved for the application’s use. You can use
this attribute to associate a unique identifier, or a pointer to a private structure,
with each menu item.
77 This is why menu items are counted starting with one, rather than zero: so that a zero return value would
represent the null selection whether the menu show () was returning the value of the selected item or the item
itself.
78 Action procedures are discussed in detail in Section 12.7, Callback Procedures.
microsystems
Revision A, of May 9, 1988
230 SunView 1 Programmer’s Guide
Item Margins The diagram below illustrates the layout of a menu item:
Figure 12-1 Layout of a Menu Item
margin
margin
left
margin
string
pull-right
arrow
(if any)
right
margin
margin
margin
menu_margin represents the margin, in pixels, around an item in a menu. Its
default value is 1.
You can set an individual item’s margin by setting the menu item. To set the
margins for all items in a menu, set the menu’s margin.
You can adjust the horizontal placement of text in menu items with
MENU_LEFT_MARGIN and MENU_RIGHT_MARGIN . 79
As with MENU_MARGIN , the left and right margins can be set either for an indi¬
vidual menu item or for the menu itself, in which case the settings will apply to
all the items in the menu. (The attributes MENU_FONT and MENU_BOXED also
work this way.)
12.3. Examples
Example 4:
Our next example will show several variations on a simple menu that could be
used for selecting font point sizes. The default form is shown to the left.
You could create the items with MENU_STRINGS, as in the previous example.
Alternately, you could create the menu with no items, then use menu_set () to
append the items to the menu: 80
79 The placement of images is currently not affected by the settings of the left and right margins.
80 Note that using MENU STRING ITEM with menu set () has the effect of an implicit append. Several
attributes are provided to explicitly add items to a menu — see Table 12-1, Attributes to Add Pre-Existing Menu
Items , later in this section.
Revision A, of May 9,1988
Chapter 12 — Menus 231
MENU_STRING_ITEM takes as values the item’s string and its value.
Now let’s see some of the ways in which the appearance of this basic menu can
be altered.
By setting MENU_INACTIVE to TRUE for an item, you can “gray out” the item
to indicate to the user that it is not currently selectable.
The menu to the left could be produced by:
f
for
(i =
4; i <= 6; i++) {
A
)
item
menu_
= menu_get (m, MENU_NTH_ITEM, i) ;
set(item, MENU_INACTIVE, TRUE, 0);
s,
J
Inactive items do not invert when the cursor passes over them.
The call menu_set(m, MENU_BOXED, TRUE, 0) will cause a single¬
pixel box to be drawn around each item. With the default margin of 1 pixel, this
will result in two-pixel lines between each item.
Increasing the margin, by setting MENU_MARGIN to 5, will cause the items to
spread out evenly, and the boxes to appear as individual boxes rather than divid¬
ing lines.
You can control the layout of the items within a menu with the attributes
MENU_NCOLS and MENU_NROWS. Suppose you wanted the menu to be laid out
horizontally instead of vertically:
All you need do is specify at create time that the menu will have 6 columns with
a call such as menu_set (m, MENU_NCOLS, 6, 0).
You can use MENU_NCOLS or MENU_NROWS to create two-dimensional menus,
as well. The call menu_set (m, MENU_NCOLS, 3, 0) will cause the
menu package to begin a second row after the first three columns have been filled
with items:
Revision A, of May 9, 1988
232 SunView 1 Programmer’s Guide
The previous example specified that the menu have 3 columns. Specifying that it
have 2 rows via MENU_NROWS would have the same effect. Items are laid out
from upper left to lower right, in “reading order,” regardless of how the layout is
specified.
8
18
12
14
16
18 1
The only time you need to specify both the number of rows and the number of
columns is when you want to fix the size of the menu, regardless of how many
items it contains. Setting MENU_NCOLS to 3 and MENU_NROWS to 3 would pro¬
duce:
If both dimensions of the menu are fixed and more items are given than will fit,
the excess items will not appear.
8
18
12
14
16
18
You can remove the menu’s shadow by setting MENU_SHADOW to null:
The menu package provides three predefined pixrects for the menu shadow. The
call menu_set (m, MENU_SHADOW, &menu_gray25_pr) produces the
25 percent gray pattern shown on first menu below. Note that these are pixrects,
not pixrect pointers. The other two patterns are produced by using
menu_gray50_pr and menu_gray75_pr:
8
18
12
14
16
18
Example 5: Let’s take the size menu from the previous example and use it to create the more
complex menu shown below, which the user could use to select both a font fam¬
ily and a point size within the family. This illustrates the multiple usage of a sin¬
gle menu. Pulling right over any of the items in the family menu will bring up
the menu for selecting point size, as shown on the left.
#sun
xr microsystems
Revision A, of May 9,1988
Chapter 12 — Menus 233
By using MENU_ITEM, we can give each item in the font family menu its string,
the font in which to render the string, and the size menu as a pull-right:
f —
\
family__menu = menu create (
MENU_ITEM,
MENU_STRING,
"Courier”,
MENU
_FONT,
cour.
MENU_PULLRIGHT,
size_menu.
0 ,
MENU_ITEM,
MENU_STRING,
"Serif ",
MENU
FONT f
serif.
MENU_PULLRIGHT,
size_menu f
0 ,
MENU_ITEM,
MENU_STRING,
"aplAPLGIJ",
MENU
FONT,
apl.
MENU_PULLRIGHT,
size_menu f
0 ,
MENU_ITEM,
MENU_STRING,
"CMR ",
MENU
FONT,
cmr.
MENU_PULLRIGHT f
size_menu,
0 ,
MENU_ITEM f
MENU_STRING f
"Screen" f
MENU
_FONT,
screen.
MENU__PULLRI GHT ,
size_menu f
0 ,
0);
s_
_>
Courier
=» |
Serif
=> 1
1 8
CUR
10 1
Screen
12
14
16
18
Suppose the font family menu had already been created, and we wanted to add
the size menu as a pull-right to each item of the existing menu. We could do this
using the attributes MENU_NITEMS and MENU_NTH_ITEM. The loop below
iterates over each item in the menu, retrieving the item’s handle and setting the
pull-right for the item:
--
for (i = (int) menu_get (family_menu, MENU__NITEMS) ; i > 0; —i)
menu_set (menu_get (family_menu, MENU_NTH_ITEM, i) ,
MENU_PULLRIGHT, size_menu, 0) ;
v_/
Revision A, of May 9, 1988
234 SunView 1 Programmer’s Guide
Example 6:
You can insert new items into an existing menu with MENU_INSERT. For
example, suppose you want to insert blank lines into the font family menu, to
indicate grouping:
You can do this by inserting non-selectable items into the menu:
-'l
menu_set (family_menu,
MENUJENSERT,
2 ,
menu_create__item (MENU_STRING, " " f
MENU__FEEDBACK , FALSE,
0 ), "
0 );
menu_set (family_menu,
MENUHINSERT,
5,
menu_get (family_menu f MENU_NTH_ITEM, 3) ,
0 );
S- )
MENU_INSERT takes two values: the number of the item to insert after, and the
new item to insert. Disabling MENU_FEEDBACK makes the item non-selectable.
The above example uses menu_create_item () to explicitly create the item
to be inserted. Usually menu items are created implicitly, using the attributes
described in Table 12-2, Menu. Item Creation Attributes, in the next section.
NOTE menu_create_item () does not set the MENU_RELEASE attribute by
default, so that the resulting item will not be automatically destroyed when its
parent menu is destroyed. This is in contrast to implicitly created menu items —
see Section 12.5, Destroying Menus.
V microsystems
Revision A, of May 9,1988
Chapter 12 — Menus 235
In addition to MENU_INSERT, there are several other attributes you can use to
add pre-existing menu items to a menu. 81 They are summarized in the following
table.
Table 12-1 Attributes to Add Pre-Existing Menu Items
Attribute
Value Type
Description
MENU_AP P END__ITEM
Menu_item
Append item to end of menu.
MENU_INSERT
int, Menu_item
Insert new item after nth item
(use n=0 to prepend).
MENU_INSERT_ITEM
Menu_item(old),
Menu_item (new)
Insert new item after old item.
MENU__RE P LACE
int, Menu_item
Replace nth item with specified item.
MENU_REP LACE_ITEM
Menu_item(old),
Menu_item (new)
Replace old item with new item
in the menu (old item is not replaced
in any other menus it may appear in).
81 To delete items from a menu, use MENU_REMOVE or MENU_REMOVE_ITEM, described in the Menu
Attributes table in in Chapter 19, SunView Interface Summary.
microsystems
Revision A, of May 9, 1988
236 SunView 1 Programmer’s Guide
Example 7:
Frame =»
Fami ly =»
Size =*►
Bold
On
Ital
For the next example we will attach the on-off, family and size menus of the pre¬
vious examples as pull-rights to a higher-level menu for selecting fonts:
font_menu * menu_create(
MENU_P ULLRIGHT_ITEM,
MENU_P ULLRI GHT__I TEM,
MENU_P ULLRIGHT_ITEM,
MENUJPULLRI GHT_I TEM,
MENU_P ULLRI GHT_I TEM,
0 );
"Frame",
"Family",
"Size",
"Bold",
"Italic",
frame__menu f
family__menu,
size__menu,
on_of f_menu,
on_of f_menu.
MENU_PULLRIGHT_ITEM takes a string and a menu as values. It creates an
item represented by the string and with the menu as a pull-right.
Note that on_of f menu is used as a pull-right for both the bold and the italic
menu items, and that the size_menu appears both as a pull-right from main
level f ont_menu and from each item in f amily_menu. This demonstrates
that a menu may have more than one parent. However, recursive menus are not
allowed — if Ml is a parent of M2, M2 (or any of its children) may not have Ml
as a child. Displaying such a recursive menu will probably result in a segmenta¬
tion fault
The ‘Frame’ item takes as its pull-right the menu which has been retrieved from
the frame using WIN_MENU.
The program fontjnenu, printed in Appendix A, Example Programs, builds
further on the above examples.
microsystems
Revision A, of May 9, 1988
Chapter 12 — Menus 237
12.4. Item Creation The attribute MENU_ITEM, introduced in Example 2, suffices to create any type
Attributes of menu item. However, several attributes are provided for convenience as a
shorthand way to create items with common attributes. These attributes, along
with the types of values they take and the type of item they create, are summar¬
ized in the following table:
Table 12-2 Menu Item Creation Attributes
Attribute
Value Type
Type of Item Created
MENU_ACT ION_IMAGE
image, action proc
Image item w/action proc.
MENU_AC TION_ITEM
char *, action proc
String item w/action proc.
MENU_GEN_PULLRIGHT_IMAGE
Pixrect *, proc
Image item with
generate proc for pull-right.
MENU_GEN_PULLRIGHT_ITEM
char *, proc
String item with
generate proc for pull-right.
MENU_IMAGE_ITEM
Pixrect *, value
Image item w/value.
MENU_IMAGES
list of Pixrect *
Multiple image items.
MENU_PULLRIGHT_IMAGE
Pixrect *, Menu
Image item w/pull-right.
MENU_PULLRIGHT_ITEM
char *, Menu
String item w/pull-right.
MENU_STRING_ITEM
char *, value
String item w/value.
MENU_STRINGS
list of char *
Multiple string items.
We could now create the menu in Example 2 more compactly by using
MENU_PULLRIGHT_ITEM instead of MENU_ITEM:
' ---v
m - menu_create(MENU_PULLRIGHT_ITEM, "Bold", on_off_menu,
MENU_PULLRIGHT_ITEM, "Italic", on_off_menu,
0 ),
--- ,
XT microsystems
Revision A, of May 9,1988
238 SunView 1 Programmer’s Guide
12.5. Destroying Menus Both menus and menu items are destroyed with the function:
void
menu_destroy(menu_object)
<Menu or Menu item> menu_ob ject;
CAUTION Watch out for dangling pointers when using a menu item in multiple menus. The
attribute MENU_RELEASE (which takes no value) controls whether or not a
menu item is automatically destroyed when its parent menu is destroyed.
MENU_RELEASE is set to TRUE by default for menu items created in-line via
the menu item creation attributes. This can lead to dangling pointers, if the same
menu item appears multiple times, because calling menu_destroy () can lead
to items being destroyed multiple times. This warning also applies to pull-rights
which are used multiple times. To prevent this error, remove multiple
occurrences of an item or pull-right before destroying a menu.
Calling menu_destroy_with j>roc () instead of menu_destroy ()
when you want to destroy a menu lets you specify a procedure to be called as the
menu or menu item is destroyed, lets you specify a procedure to be called every
time a particular menu or menu item is about to be destroyed:
void
menu_destroy_with_proc (menu_ob ject, destroy_j?roc)
<Menu or Menu_item> menu_ob ject;
void (*destroy_proc) ();
Your destroy procedure should be of the form:
void
destroy__proc (menu_ob ject f type)
<Menu orMenu_item> menu_object;
Menu_attribute type;
For menus, menu_ob j ect is the menu and the type parameter is
MENU_MENU; for menu items, menu_ob ject is the item and the type param¬
eter is MENU ITEM.
microsystems
Revision A, of May 9, 1988
Chapter 12 — Menus 239
12.6. Searching for a Menu
Item
The function menu__f ind () lets you search through a menu (and its children)
to find a menu item meeting certain criteria:
Menu_item
menu__f ind (menu, attributes) ;
Menu
menu;
<attribute-list> attributes;
For example, the following call searches for the menu item whose string was
“Load New File”, menu find() will return itNULLif
r
whose string was "Load New File":
v
By default, menu_f ind () uses a “deferred” search — searching all the items
in a menu before descending into any pull-rights which may be present. By set¬
ting MENU_DESCEND_FIRST (which takes no value), you can force a depth-
first search.
If multiple attributes are given, menu__f ind () will find the first item matching
all the attributes.
The following attributes are recognized by menu_f ind ():
Table 12-3 Menu Attributes Recognized by menu_f ind ()
MENU_ACTION
MENU_CLIENT_DATA
MENU_FEEDBACK
MENU_FONT
MENU__GEN__P ROC
MENU_GEN_PULLRIGHT
MENU_IMAGE
MENU INACTIVE
MENU_STRING
MENU VALUE
MENU INVERT
MENU LEFT MARGIN
MENU_MARGIN
MENU PARENT
MENUJPULLRIGHT
MENU RIGHT MARGIN
Revision A, of May 9, 1988
240 SunView 1 Programmer’s Guide
12.7. Callback Procedures When you call menu_show (), the menu package displays the menu, gets a
selection from the user, and undisplays the menu. The menu package allows you
to specify callback procedures which will be called at various points during the
invocation of the menu. These let you create and modify menus or respond to
the user’s actions, on the fly, at the time the user brings up the menu. There are
three types of callback procedures: generate procedures (so named because they
are called before the menu or item is displayed, allowing the application to gen¬
erate or modify the menu on the fly), notify procedures (for menus) and action
procedures (for menu items) which are called after the user has made a selection.
Flow of Control in The callback mechanism gives you a great deal of flexibility in creating, combin-
menu_show () ing and modifying menus and menu items. This flexibility comes at the price of
some complexity, however. To take advantage of it, it is necessary to understand
when the callback procedures are called after you invoke menu_show ().
For purposes of explanation, the diagrams below divide the process of displaying
a menu and getting the user’s selection into two stages, the display stage and the
notification stage.
microsystems
Revision A, of May 9,1988
Chapter 12 — Menus 241
Figure 12-2 Display Stage of Menu Processing
Start menu show ()
To Notification Stage
microsystems
Revision A, of May 9, 1988
242 SunView 1 Programmer’s Guide
Figure 12-3 Notification Stage of Menu Processing
From Display Stage
Return from menu_show ()
Generate Procedures The first argument to a generate procedure is either a menu or menu item depend¬
ing on whether it’s a MENU_GEN_PROC or a MENU_GEN_PROC_lTEM. Also
passed in is an operation indicating at which point in the processing of the menu
the generate procedure is being called. The operation parameter is of type
Menu_generate, and may be MENU_DISPLAY, MENU_DISPLAY_DONE,
MENU_NOTIFY or MENU_NOTIFY_DONE . 82
NOTE The menu package uses the fullscreen access mechanism when displaying the
menu. Writing to the screen while under fullscreen access will probably cause
your program to deadlock, so your generate procedure should not access the
screen when called with an operation o/MENU_DISPLAY or
MENU DISPLAY DONE.
82 For a detailed explanation of when the generate procedures are called in relation to the other callback
procedures, see the diagrams in the next subsection. Flow of Control in menu_show ().
Revision A, of May 9,1988
Chapter 12 — Menus 243
There are three types of generate procedures — menu item generate procedures,
menu generate procedures, and pull-right generate procedures. A description
and example of each is given below.
Menu Item Generate Procedure A generate procedure attached to a menu item has the form:
Menu_item
menu_item_gen_proc(item, operation)
Menu_item item;
Menu_generate operation;
You can specify a menu item generate procedure via MENU_GEN_PROC.
Example 8:
The most common use of menu item generate procedures is to modify the item’s
display string. The program listed below registers a generate procedure,
toggle_proc (). If it has been called from the menu_display stage of
processing, it toggles the text of the ‘Redisplay’ item on the frame menu.
#include <suntool/sunview.h>
Menu_item togglejproc();
int toggle = 0;
main ()
{
Window frame = window_create(NULL, FRAME, 0) ;
Menu menu = window_get(frame, WIN_MENU);
Menu_item item = menu__find (menu,
MENU_STRING, "Redisplay", 0);
menu_set(item , MENU_GEN_PROC, toggle_proc, 0);
window_main_loop (frame) ;
}
Menu__item
toggle_j?roc(mi, op)
Menu__item mi;
Menu_generate op;
{
switch (op) {
case MENU_DISPLAY:
if (toggle) {
menu_set(mi,
MENU__STRING, "Redisplay has been seen",
0 ); ’
} else {
menu__set (mi,
MENU_STRING, "Redisplay",
0 ); "
}
toggle = !toggle;
break;
case MENU_DISPLAY_DONE:
case MENU NOTIFY:
sun
microsystems
Revision A, of May 9,1988
244 SunView 1 Programmer’s Guide
Menu Generate Procedure
Example 9:
r
case MENU_NOTIFY_DONE:
break;
}
return mi; /* item handle always returned */
}
_/
The ‘Zoom’/‘Unzoom’ item in the SunView frame menu also uses this technique
to toggle its display string. Note that since this item knows how to modify itself,
you could put it in other menus and get the same behavior. A generate procedure
for a menu item allows the application to be called even when it has no
knowledge of or control over the call to menu_show ().
A generate procedure attached to a menu has the form:
Menu
menu_gen_jproc (m, operation)
Menu m;
Menu_generate operation;
You can specify a menu generate procedure via the attribute MENU_GEN_PROC.
We will take as an example a menu allowing the user to list different groups of
files. When the user makes a selection, we generate a menu containing the
correct set of files:
List dot files => |
List bin dir
clock |
shelltool I
iconedit
List all files
The relevant functions are listed on the next page. The first,
initialize_menu (), creates the three menu items, giving each of them the
generate procedure list_f iles (), and a unique identifier as
MENU_C LIENT_DATA.
Remember that list_f iles () is called in four different situations by
menu_show () : 83
□ When the operation is MENU_D ISP LAY, the pull-right is being asked to
display its menu, so list_f iles () calls the function
get_f ile_names () (not shown) to get the appropriate list of file names.
83 See the diagrams in the earlier subsection. Flow of Control in menu show ().
microsystems
Revision A, of May 9, 1988
Chapter 12 — Menus 245
and adds each name in the list to the menu.
□ When list_files () is called with operation set to
MENU_D I SPLAY_DONE, the menu of generated file names is no longer
being displayed. list_files() cleans up by destroying the old menu of
file names, replacing it with a fresh menu with the same generate procedure.
It returns the handle of this new menu.
o Whenlist_files () is called with an operation of MENU_N0TIFY
or MENU NOTIFY DONE, the menu is returned unaltered.
#define DOT 0
#define BIN 1
#define ALL 2
static void
initialize_menu(menu)
Menu menu;
{
m = menu_create (MENU_GEN_PROC, list_files f
MENU_CLIENT_DATA, DOT,
0 ); "
menu_set (menu,
MENU_PULLRIGHT_ITEM, "List dot files", m,
0 ); "
m = menu_create (MENU_GEN__PROC, list__files,
ME NU_CLIENT_DATA, BIN,
0 ); "
menu_set (menu,
MENU__PULLRIGHT_ITEM, "List bin dir", m,
0 ); “
m = menu_create (MENU_GEN_PROC, list_files,
MENU_CLIENT_DATA, ALL,
0 ); "
menu__set (menu,
MENU_PULLRIGHT_ITEM, "List all files", m,
0 ); "
static Menu
list_files(m, operation)
Menu m;
Menu_generate operation;
{
char **list;
int directory;
int i = 0;
switch (operation) {
case MENU_DISPLAY:
directory = (int)menu_get(m, MENU_CLIENT_DATA) ;
list = get_file__names (directory);
while (*list)
menu_set (m,
MENU_STRING_ITEM, *list++, i++,
0 );
break;
sun Revision A, of May 9,1988
microsystems
246 SunView 1 Programmer’s Guide
case MENU_DISPLAY_DONE:
/*
* Destroy old menu and all its entries.
* Replace it with a new menu.
*/
directory = (int) menu__get (m, MENU_CLIENT_DATA) ;
menu_destroy (m) ;
m = menu_create (MENU_GEN_PR0C, list_files,
MENU_CLIENT_DATA, directory,
0 ); "
break;
case MENU__NOTIFY:
case MENU_NOTIFY_DONE:
break;
/* The current or newly-created menu is returned */
return m;
Pull-right Generate Procedure You can postpone the generation of a pull-right menu until the user actually pulls
right by specifying a pull-right generate procedure. A pull-right generate pro¬
cedure has the form:
Menu
pullright_gen_j?roc (mi, operation)
Menu__item mi;
Menu_generate operation;
Note that the pull-right generate procedure is passed the item, and returns the
menu to be displayed.
You can specify a menu item’s pull-right generate procedure with a call such as
/— - — >
menu_set (menu__item, MENU_GEN_PULLRIGHT, my__pullright__gen f 0) ;
---'
Alternatively, you can use the attributes MENU_GEN_PULLRIGHT_IMAGE or
MENU_GEN_PULLRIGHT_ITEM to give a menu both an item and the item’s
generate procedure.
If you want to get the existing menu for an item which has a pull-right generate
procedure, retrieve the value of the item, as in:
--— >
menu = menu_get (item, MENU_VALUE) ;
Revision A, of May 9,1988
Chapter 12 — Menus 247
Notify/Action Procedures
When the user selects a menu item by releasing the mouse button, the menu
package calls back to any notify procedures or action procedures you have
specified. Notify procedures and action procedures have the form:
caddr_t
notify_proc(m, mi)
Menu m;
Menu_item mi;
The most common usage is to have action procedures for the items at the leaf
nodes of the walking menu. The general mechanism described below is provided
to allow your procedures to be called for non-leaf nodes as well.
Imagine a chain of menus expanded out. Lookup of the notify/action procedures
starts with the “oldest” menu, the one passed to menu_show (). If it has a
notify procedure, that notify procedure is called, otherwise the default notify pro¬
cedure, menu_return_value (), is called. Likewise, for each menu down
the chain, until the menu with the selected item is reached. If the selected item
has an action procedure, that action procedure is called. If the selected item is
not on a leaf node, then action procedures for any items farther down the chain
are also called.
Let’s see what happens in the example to the left (assume that ‘On’ is the default
item for the first menu):
If ‘Italic’ was selected:
□ no callback to the first menu’s notify procedure since an item in it is
selected,
□ callback to the action procedure for the ‘Italic’ item,
□ no callback to the second menu’s notify procedure since it is further down
the chain than the selected item,
□ callback to the action procedure for the ‘On’ item.
If ‘Off was selected:
□ callback to the notify procedure for the first menu, since an item in a menu
further down the chain than it is selected,
□ no callback to the action procedure for the ‘Italic’ item, since it is above the
selected item in the chain,
□ no callback to the second menu’s notify procedure since an item in it is
selected,
□ callback to the action procedure for the ‘Off item.
NOTE If you specify a notify procedure, it is your responsibility to propagate the
notification to any menus further down in the chain. You can do this by calling
menu_get (mi, MENU_VALUE) from your notify procedure. This gets the
value of the selected menu item, and since the value of a pull-right item is the
microsystems
Revision A, of May 9, 1988
248 SunView 1 Programmer’s Guide
value of its pull-right menu, this will make notify/action procedures further down
the chain get called.
12.8. Interaction with Walking Menus for frames and tty subwindows can be customized. 84 All menu
Previously Defined items in these menus are “position-independent” — in other words the menus do
SunView Menus not count on a given item having a certain position or being located in a particu¬
lar menu. This makes it possible for you to safely add new items (including
pull-right submenus) to an existing menu.
NOTE You should not use the client data field of items created by SunView packages,
because the packages have pre-empted it for their own use.
Using an Existing Menu as a The program fontjnenu, listed in Appendix A, shows how you can replace an
Pull-right existing menu with your own menu which has the original menu as a pull-right.
Making use of several of the examples given earlier in the chapter, it creates a
font menu which allows the user to select the font family, point size, and whether
or not the font is bold or italic. Meanwhile, the first item, labelled ‘Frame’,
brings up the original frame menu:
Frame
Close |
Family
Hove => |
Size
Resize => |
Bold
Expose
Italic
Hi de
Redisplay 1
Quit
84 Remember that in order to have these packages use walking menus the user must have enabled the
Walking Menus option in SunView category of defaultsedit(l); in SunOS Release 4.0, this is the default.
©sun
XT microsystems
Revision A, of May 9, 1988
Chapter 12 — Menus 249
12.9. Initial and Default Two special menu items are the default item (MENU_DEFAULT_ITEM) and the
Selections selected item (MENU_SELECTED_ITEM). The default item is simply a dis¬
tinguished item. The selected item is the item which was last selected.
Two attributes are provided to control the behavior of a menu in regard to its ini¬
tial selection. If MENU_INITIAL_SELECTION_SELECTED is TRUE, the
menu comes up with its initial selection selected — that is the selection is
inverted and the cursor is positioned over it. If FALSE, the menu comes up with
the cursor “standing off’ to the left and no selection highlighted. If
MENU_INITlAL_SELECTION_EXPANDED is TRUE, when the menu comes
up, it automatically expands any pull-rights which are necessary to bring the ini¬
tial selection up on the screen.
Each menu also has an initial selection (MENU_INITIAL_SELECTI0N) and a
default selection. (MENU_DEFAULT_SELECTION).
The distinction between the initial selection and the default selection is subtle.
Suppose MENU_INITIAL_SELECTI0N_EXPANDED was TRUE, and the ini¬
tial selection was an item in a pull-right. When the menu comes up, it will be
expanded to show the initial item as selected. However, if the user moves the
cursor to the left, backing out of the pull-right, and then moves back to the right,
bringing the pull-right up again, the item selected will be the default selection
rather than the initial selection.
When the user selects a pull-right item without bringing up the associated menu,
it is as if he had brought the pull-right up and selected the default item.
You can set the initial selection and the default selection independently — either
can be set to the default item or the selected item.
microsystems
Revision A, of May 9,1988
250 SunView 1 Programmer’s Guide
12.10. User Customizable The user can specify the values of certain menu attributes in the Menu category
Attributes of default sedit (1). When a menu is created, for attributes not explicitly
specified by the application program, the menu package retrieves the values set
by the user from the defaults database maintained by default sedit. This
allows the user the ability to tailor, to some extent, the appearance and behavior
of menus across different applications. For example, he may want to change the
type of shadow, or expand the menu margin, and so on.
The attributes under default sedit control are listed in the following table.
Table 12-4 User Customizable Menu Attributes
Attribute
Default
Description
MENU_BOXED
FALSE
If TRUE, a single-pixel box will be
drawn around each menu item.
MENU_DEFAULT_SELECTION
MENU_DEFAULT
MENU_SELECTED or MENU_DEFAULT.
MENU_FONT
screen.b.12
Menu’s font.
MENU_INITIAL_SELECTION
MENU_DEFAULT
MENU_SELECTED or MENU_DEFAULT.
MENU_INITIAL_SELECTION_SELECTED
FALSE
If true, menu comes up with its initial
selection highlighted. If FALSE, menu comes
up with the cursor "standing off to the left.
MENU_INITIAL_SELECTION_EXPANDED
TRUE
If true, when the menu pops up, it auto¬
matically expands to select the initial selection.
MENU_JUMP_AFTER_NO_SELECTION
FALSE
If true, cursor jumps back to its
original position after no selection made.
ME NU_JUMP_AF T E R_S ELECTION
FALSE
If TRUE, cursor jumps back to its
original position after selection made.
MENU_MARGIN
1
The margin around each item.
MENU_LEFT_MARGIN
16
For each string item, margin in addition to
MENU_MARG IN on left
between menu’s border and text.
MENU_PULLRIGHT_DELTA
9999
# of pixels the user must move the cursor to
the right to cause a pull-right menu to pop up.
MENU_RIGHT_MARGIN
6
For each string item, margin in addition to
MENU_MARGIN on right
between menu’s border and text.
MENU SHADOW
50% grey
Pattern for menu’s shadow.
microsystems
Revision A, of May 9, 1988
Cursors
253
13.1. Creating and Modifying Cursors
13.2. Copying and Destroying Cursors
13.3. Crosshairs.
13.4. Some Cursor Attributes.
Cursors
This chapter describes how to create and manipulate cursors , 85 A cursor is an
image that tracks the mouse on the display. Each window in SunView has its
own cursor, which you can change with the cursor package.
If it is installed on your system, you can run the demo
/usr/demo/cur sor_demo to see the effects of various cursor attributes.
The source for this is in
/usr/src/share/sun/suntool/cursor_demo.c.
Header Files The definitions necessary to use cursors are found in the include file
<sunwindow/win_cursor . h>, which is included by default when you
include the file <suntool/sunview.h>.
Summary Listing and Tables To give you a feeling for what you can do with cursors, the following page con¬
tains a list of the available cursor attributes and functions. Many of these are dis¬
cussed in the rest of this chapter and elsewhere (use the Index to check). All are
briefly described with their arguments in the cursor summary tables in Chapter
19, SunView Interface Summary:
□ the Cursor Attributes table begins on page 321;
a the Cursor Functions table begins on page 323.
85 The cursor is called the “pointer” in user-level documentation.
microsystems
253
Revision A, of May 9, 1988
254 SunView 1 Programmer’s Guide
Cursor Attributes
CURSOR CROSSHAIR_BORDER_GRAVITY
CURSOR_OP
CURSOR CROSSHAIR_COLOR
CURSOR_SHOW_CROSSHAIRS
CURSOR_CROSSHAIR_GAP
CURSOR_SHOW_CURSOR
CURSOR_CROSSHAIR_LENGTH
CURSOR_SHOW_HORIZ_HAIR
CURSOR_CROSSHAIR_OP
CURSOR_SHOW_VERT_HAIR
CURSOR_CROSSHAIR_THICKNESS
CURSOR_VERT_HAIR_BORDER_GRAVITY
CURS OR_FULLS CREEN
CURSOR_VERT_HAIR_COLOR
CURSOR_HORIZ_HAIR_BORDER_GRAVITY
CURSOR_VERT_HAIR_GAP
CURS OR_HORIZ_HAIR_COLOR
CURSOR_VERT_HAIR_LENGTH
CURSOR_HORIZ_HAIR_GAP
CURSOR_VERT_HAIR_OP
CURSOR_HORIZ_HAIR_LENGTH
CURSOR_VERT_HAIR_THICKNESS
CURSOR_HORIZ_HAIR_OP
CURSOR_XHOT
CURSOR_HORIZ_HAIR_THICKNESS
CURSOR_YHOT
CURSOR_IMAGE
Cursor Functions
cursor__copy (src_cursor)
cursor_create(attributes)
cursor_destroy(cursor)
cursor_get(cursor,
cursor_set (cursor.
attribute)
attributes)
microsystems
Revision A, of May 9,1988
Chapter 13 — Cursors 255
13.1. Creating and
Modifying Cursors
13.2. Copying and
Destroying Cursors
Example 1: Creating a Window
with a Custom Cursor
The basic usage of the cursor package is to first create a cursor with
cursor_create (), and then use this cursor as the value of the
WlN_CURSOR attribute in your call to window_create ().
Cursor
cursor_create(attributes)
<attribute-list> attributes;
Once you have created a cursor, you can alter its attributes with
cur sor__set () and read back its attributes with cursor_get ():
void
cursor_set(cursor, attributes)
Cursor cursor;
<attribute-list> attributes;
caddr_t
cursor__get (cursor, attribute)
Cursor cursor;
Cursor_attribute attribute;
If you want to change the cursor of a window that has already been created, you
can first get the cursor from the window using window_get () of
WlN_CURSOR, then use cur sor_set () to change the cursor, and then use
window_set () of WIN__CURSOR to re-attach the cursor to the window.
A copy of an existing cursor can be made with cur sor_copy ():
Cursor
cursor_copy(src_cursor)
Cursor src__cursor;
A cursor can be destroyed and its resources freed with cur sor_destroy ():
void
cursor_destroy(cursor)
Cursor cursor;
A common use for cursors might be to create a canvas subwindow and have it
use the cursor of your choice, rather than the default arrow cursor:
13.1. Creating and
Modifying Cursors
13.2. Copying and
Destroying Cursors
Example 1: Creating a Window
with a Custom Cursor
Revision A, of May 9, 1988
256 SunView 1 Programmer’s Guide
short my_pixrect_data[] = {
#include "fdejromjconedit"
};
mpr_static(my_pixrect, 16, 16, 1, my_j>ixrect__data) ;
Canvas canvas;
init__my_canvas ()
{
canvas = window_create(frame, CANVAS,
WIN__CURSOR, cursor_create (CURSOR_IMAGE,
0 ),
}
0 );
&my_pixrect.
This example creates a cursor “on the fly” and passes it into the
window_create () routine for use with the canvas. The attribute
CURSOR_IMAGE is set to the a pointer to the pixrect we want to use (a diamond
or bullseye, for example). All of the other cursor attributes default to the value
shown in the attribute table.
Example 2: Changing the Suppose you have already created a window and you want to change its cursor.
Cursor of an Existing Window Let’s say you want to change the drawing op to P IX_SRC:
r
Cursor cursor;
>
cursor = window get (my_window, WIN__CURSOR) ;
cursor^set (cursor, CURSOR__OP, PIX_
SRC, 0);
\_
window set (my_window, WIN_CURSOR,
cursor, 0);
_/
CAUTION The cursor returned by window_get () is a pointer to a static cursor that
is shared by all the windows in your application. So, for example, saving the
cursor returned by window_get () and then making other window system calls
might result in the saved cursor being overwritten. 86
It is safe to get the cursor, modify it with cursor_set () and then put the cur¬
sor back. If there is any chance that the static cursor will be overwritten, you
should use cursor_copy () to make a copy of the cursor, then use
cursor_destroy () when you are done.
13.3. Crosshairs Crosshairs are horizontal and vertical lines whose intersection tracks the location
of the mouse. You can control the appearance of both the horizontal and vertical
crosshairs along with the cursor image. For example, you can create a cursor that
only shows the cursor image, or only the horizontal crosshair, or both the hor¬
izontal and vertical crosshairs and the cursor image. By default both the
crosshairs are turned off and only the cursor image is displayed.
86 Note that this would happen if one of the routines you call happens to call window get () of
WIN CURSOR.
Revision A, of May 9, 1988
Chapter 13 — Cursors 257
Example 3: Turning on the Suppose you have a canvas window in which you want to turn on both the hor-
Crosshairs izontal and vertical crosshairs. This can be done by getting the cursor from the
window and setting the CURSOR_SHOW_CROSSHAlRS attribute:
( ----N
Cursor cursor;
cursor * window_get (my__canvas, WIN_CURSOR) ;
cursor_set(cursor, CURSOR_SHOW_CROSSHAIRS, TRUE, 0);
window_set (my_canvas, WIN_CURSOR, cursor, 0) ;
V---_>
When the crosshairs are turned on, they are displayed according to the current
value of their other attributes (e.g. thickness and drawing op).
This section describes some of the cursor attributes in more detail. Note that for
the crosshair attributes, you can control the individual crosshairs as well as both
crosshairs by using the appropriate attribute. For example, you can set the length
for both crosshairs with CURSOR_CROSSHAIR_LENGTH or the length of only
the horizontal crosshair with CURSOR_HORIZ_HAlR_LENGTH.
cursorjmage The cursor image is the memory pixrect that is drawn on the screen as the mouse
moves. Use the mpr_static () macro, as shown in Example 1, to create the
memory pixrect. The image is represented as an array of 16 shorts, each of
which represents a 16-pixel wide scan line. The scan lines are usually arranged
in a single column, yielding a 16 x 16 pixel image. Other arrangements, such as
32 pixels wide x 8 pixels deep, are also possible. The maximum size of a cursor
in SunView 1 is 32 bytes; the minimum width is 16, the width of one scan line.
cursorjchot and cursor.yhot The “hot spot” defined by ( CURSOR_XHOT, CURSOR_YHOT ) associates the
cursor image, which has height and width, with the mouse position, which is a
single point on the screen. The hot spot gives the mouse position an offset from
the upper-left comer of the cursor image. For example, if the upper left comer of
the cursor image is at location (50,40) and the cursor hot spot has been set to (8,
8), the reported mouse position will be at (58,48).
Most cursors have a hot spot whose position is obvious from the image shape:
the tip of an arrow, the center of a bullseye, the center of a cross-hair. Cursors
can also be used to give status feedback — an hourglass to indicate that the pro¬
gram is not responding to user input is a typical example. This type of cursor
should have the hot spot located in the middle of its image so the user has a
definite spot for pointing and does not have to guess where the hot spot is.
cursor_op The value given for this attribute is the rasterop which will be used to paint the
cursor. 87 PIx_SRC | PIX_DST is generally effective on light backgrounds —
in text, for example — but invisible over solid black. PIx_S RC ~ Pix_DST
is a reasonable compromise over many different backgrounds, although it does
poorly over a gray pattern.
13.4. Some Cursor
Attributes
87 Rasterops are described fully in the Pixrect Reference Manual.
Xr microsystems
Revision A, of May 9, 1988
258 SunView 1 Programmer’s Guide
CURSOR_FULLSCREEN
The cursor crosshairs can be clipped to either the cursor’s window or the entire
screen. If you want the crosshairs to extend past the edge of the window, set
CURSOR_FULLSCREEN to TRUE.
CURSOR_CROSSHAIR_LENGTH
If you don’t want the crosshairs to cover the entire window (or screen), you can
set the length of both crosshairs with CURSOR_CROSSHAlR_LENGTH. The
value of this attribute is actually half the total crosshair length. For example, if
you want the crosshairs to be 400 pixels wide and high, set the
CURSOR CROSSHAlR_LENGTH to 200. You can restore the extend-to-edge
length by giving a value of CURSOR_TO_EDGE for
CURSOR CROSSHAIR LENGTH.
cursor_crosshair_border_gravity If the crosshair border gravity is enabled, the crosshairs will "stick” to the edge of
CURSOR_CROSSHAIR_GAP
the window (or screen). This is only interesting if the
CURSOR_CROSSHAIR_LENGTH is not set to CURSOR_TO_EDGE. With
border gravity turned on, each half of each crosshair will be attached to the edge
of the window. With the cursor image displayed, this feature might be useful to
help the user line up the cursor to a grid drawn on the edges of the window.
If you don’t want the halves of each crosshair to touch, you can set the
CURSOR CROSSHAIR GAP to the half-length of space to leave between each
crosshair half. If you set CURSOR_CROSSHAIR_GAP to CURSOR_TO_EDGE,
the crosshairs will back off to the edge of the CURSOR_iMAGE rectangle.
XT microsystems
Revision A, of May 9,1988
Icons
Icons
261
14.1. Using Images Generated With iconedit
14.2. Modifying the Icon’s Image.
14.3. Loading Icon Images At Run Time.
262
263
263
Header Files
Summary Listing and Tables
14
Icons
An icon is a small (usually 64 by 64 pixel) picture representing a base frame in
its closed state. The icon is typically a picture indicating the function of the
underlying application.
The definitions necessary to use icons are found in the file
<suntool/icon. h>, which is included by default when you include the file
<suntool/sunview. h>.
To give you a feeling for what you can do with icons, the following page lists the
available icon attributes, functions and macros. Many of these are discussed in
the rest of this chapter and elsewhere (use the Index to check). All are briefly
described with their arguments in the menu summary tables in Chapter 19, Sun-
View Interface Summary:
□ the Icon Attributes table begins on page 328;
□ the Icon Functions and Macros table begins on page 329.
IN un
\r microsystems
261
Revision A, of May 9,1988
262 SunView 1 Programmer’s Guide
Icon Attributes
ICON_FONT
ICON_IMAGE_RECT
ICON_WIDTH
ICON_HEIGHT
ICON_LABEL
ICON_IMAGE
ICON_LABEL_RECT
Icon Functions and Attributes
icon_create(attributes)
icon set(icon, attributes)
icon_destroy(icon)
DEFINE_ICON_FROM_IMAGE(name, image)
icon_get(icon f attribute)
14.1. Using Images
Generated With
iconedit
You can create and edit images easily using the program iconedit(l). The
output of iconedit is a file containing an array of shorts representing the
image. In order to use the image in a program, you must first define a static
memory pixrect containing this data. Thempr_static () macro is provided
for this purpose.
The first argument to mpr_static () is the name of the pixrect to be defined.
Next come the width, height and depth of the image, typically 64, 64 and 1. The
last argument is the array of shorts containing the bit pattern of the icon image.
For example:
-—- 1
static short icon_image[] = {
♦include ,, file_generated_by_iconedit"
};
mpr_static (icon__pixrect, 64, 64, 1, icon_image);
< ____J
The statically defined image is passed in to icon_create () at run time:
-—->
my_icon = icon_create (ICON_IMAGE, &icon__pixrect, 0) ;
s___ '
Once you have created an icon, you can retrieve and modify its attributes with
icon_get () and icon_set (), and destroy it with icon_destroy ().
Instead of creating the icon dynamically with icon_create (), you can use
the DEFINE_IC0N_FR0M_IMAGE () macro to generate a static icon. 88
---■>
static short icon_image[] = {
♦include "file_generated_by_iconedit"
};
DEFINE_ICON_FROM_IMAGE (icon, icon_image) ;
< __—- '
This macro statically allocates a structure representing an icon. Note that you
88 The structure generated is actually an extern.
Revision A, of May 9, 1988
Chapter 14 — Icons 263
WARNING
14.2. Modifying the Icon’s
Image
14.3. Loading Icon Images
At Run Time
must pass the address of this structure — & icon in the example above — into
icon_get (), icon_set (), and icon_destroy ().
The DEFINE_IC0N_FR0M_IMAGE () macro may not be supported in future
releases. We reccommend that you use icon_create () instead.
It is often useful to change the icon’s image dynamically, rather than simply
using the icon as a static placeholder. When mailtool receives new mail, for
example, it lets the user know by modifying its icon to show a letter arrived in
the mailbox, clocktool uses its icon to represent a moving clock face.
The steps to follow in modifying an icon’s image are:
□ get the frame’s icon (attribute FRAME_iCON);
□ get the icon’s pixrect (attribute I C0N_IMAGE);
□ modify the pixrect as desired, or substitute a new pixrect;
□ give the pixrect with the new image back to the icon;
o give the new icon back to the frame.
For example:
- -->
modify_icon(frame);
Frame frame;
Icon icon;
Pixrect *pr;
icon = (Icon) window__get (frame, FRAME_ICON) ;
pr = (Pixrect *) icon_get(icon, ICON_IMAGE);
(modify pr)
icon_set(icon, ICON_IMAGE, pr, 0);
window_set(frame, FRAME_ICON, icon, 0);
Often it is sufficient to define the image for a program’s icon at compile time,
with mpr_stat ic (). However, you may want to allow the user to create his
own icon images, and give the names of the files containing the images to your
program as command-line arguments. Then you can load the images from the
files the user has specified. Routines to load icon images from files at run time
are described in Chapter 11 of the SunView 1 System Programmer’s Guide.
WARNING
14.2. Modifying the Icon’s
Image
14.3. Loading Icon Images
At Run Time
Revision A, of May 9, 1988
Scrollbars
Scrollbars
267
15.1. Scrolling Model. 269
15.2. Scrollbar User Interface. 271
Types of Scrolling Motion. 271
Undoing a Scroll. 271
15.3. Creating, Destroying and Modifying Scrollbars. 272
15.4. Programmatic Scrolling. 275
f
V
v \
Scrollbars
The canvas, text and panel subwindows have been designed to work with
scrollbars. The text subwindow automatically creates its own vertical scrollbar.
For canvases and panels, it is your responsibility to create the scrollbar and pass
it in with the attributes WIN_VERT ICAL_S CROLLBAR or
WIN_HORIZONTAL_SCROLLBAR.
Section 15.2, Scrollbar User Interface, describes how the user interacts with
scrollbars. Basic scrollbar usage is covered in Section 15.3, Creating, Destroy¬
ing and Modifying Scrollbars, and programmatic scrolling is covered in Section
15.4, Programmatic Scrolling.
You may want to use scrollbars in an application not based on canvases, text
subwindows or panels, in which case you must manage the interaction with the
scrollbar directly. For an explanation of how to do this, see the Scrollbars
chapter in the SunView 1 System Programmer’s Guide.
Header Files The definitions necessary to use scrollbars are found in the header file
<suntool/scrollbar.h>
Summary Listing and Tables To give you a feeling for what you can do with scrollbars, the following page
contains a list of the available scrollbar attributes, functions and macros. Many
of these are discussed in the rest of this chapter and elsewhere (use the Index to
check). All are briefly described with their arguments in the scrollbar summary
tables in Chapter 19, SunView Interface Summary:
□ the Scrollbar Attributes table begins on page 362;
□ the Scrollbar Functions table begins on page 365.
microsystems
267
Revision A, of May 9, 1988
268 SunView 1 Programmer’s Guide
Scrollbar Attributes
SCROLL_ABSOLUTE_CURSOR
SCROLL_NOT I FY_CL I ENT
SCROLL_ACTIVE_CURSOR
SCROLL_NORMALIZE
SCROLL_ADVANCED_MODE
SCROLL_OBJECT
SCROLL_BACKWARD_CURS OR
SCROLL__OBJECT_LENGTH
SCROLL_BAR_COLOR
SCROLL_P AGE_BUTT ON S
SCROLL_BAR_DISP LAY_LEVEL
SCROLL_PAGE_BUTTON_LENGTH
SCROLL_BORDER
SCROLL_PAINT_BUTTONS_PROC
SCROLL_BUBBLE_COLOR
SCROLL_PIXWIN
SCROLL_BUBBLE_DISP LAY_LEVEL
SCROLL_P LACEMENT
SCROLL_BUBBLE_MARGIN
SCROLL_RECT
SCROLL_DIRECTION
SCROLL_REPEAT_TIME
SCROLL__END_P 0 INT_ARE A
SCROLL_REQUEST__MOT I ON
SCROLL_FORWARD_CURSOR
SCROLL_REQUEST_OFFSET
SCROLL_GAP
SCROLL_THICKNESS
SCROLL_HEIGHT
SCROLL_T 0_GRID
SCROLL_JL AS T_V IE W_S TART
SCROLL_TOP
SCROLL_LEFT
SCROLL_VIEW_LENGTH
SCROLL_LINE_HEIGHT
SCROLL_VIEW_START
SCROLL_MARGIN
SCROLL__WIDTH
SCROLL_MARK
_ Scrollbar Functions and Macros _
scrollbar_create(attributes) scrollbar_paint(scrollbar)
scrollbar_destroy(scrollbar) scrollbarjpaint_clear(scrollbar)
scrollbar_get(scrollbar, attribute) scrollbar_clear_bubble(scrollbar)
scrollbar_set(scrollbar, attributes) scrollbar_paint_bubble(scrollbar)
scrollbar scroll to(scrollbar, new_view_start) _
Asun
microsystems
Revision A, of May 9, 1988
Chapter 15 — Scrollbars 269
15.1. Scrolling Model
Scrollbars allow the user to control which portion of an object is visible when the
object is larger than the window it is displayed in. Within the scrollbar is a
darker area called the bubble. The size and position of the bubble within the bar
tell the user where he is in the object and how much of the object is visible. By
moving the bubble within the bar, the user brings different portions of the object
into view.
The length of the object, the length of the visible portion of the object, and the
offset of the visible portion within the object are given by the attributes
SCROLL_OBJECT_LENGTH, SCROLL_VIEW_LENGTH, and
SCROLL_VlEW_START. The relationship between these three view-space
metrics is shown in the figure on the next page.
xr microsystems
Revision A, of May 9, 1988
270 SunView 1 Programmer’s Guide
Figure 15-1 Scrolling Model
Figure 15-1 shows a two-page document being viewed within a window roughly
half the size of the document. The three view-space attributes
SCROLL_OBJECT_LENGTH, SCROLL_VIEW_LENGTH, and
SCROLL - VIEW START are shown superimposed on the document. Note the
relative size and position of the bubble within the scrollbar — it is roughly half
the size of the window and positioned near the bottom.
microsystems
Revision A, of May 9, 1988
Chapter 15 — Scrollbars 271
15.2. Scrollbar User
Interface
Types of Scrolling Motion The default scrollbar is vertical, with page buttons at the top and bottom. To
scroll, the user moves the cursor into the scrollbar (either the bar itself or one of
the page buttons) and clicks one of the mouse buttons. The following table
describes the available scrolling actions and how they are generated:
Table 15-1 Scrolling Motions
Mouse Button
Cursor Location
Scrolling Action
LEFT
page button
Line forward
RIGHT
page button
Line backward
MIDDLE
page button
Page forward
MIDDLE (shifted)
page button
Page backward
LEFT
bar
Line opposite cursor goes to top
RIGHT
bar
Top line comes to cursor
LEFT (shifted)
bar
Bottom line comes to cursor
RIGHT (shifted)
bar
Line opposite cursor goes to bottom
MIDDLE
bar
The line whose offset into the
scrolling object approximates that
of the cursor into the scrollbar is
positioned at top (“thumbing”).
Undoing a Scroll
Holding the button down within the scrollbar causes the cursor to change, pre¬
viewing the scrolling action for that button. Releasing the button causes the
scrolling action to be performed, or, if the user holds down the mouse button, the
scrolling motion will start in repeating mode.
(Shift l -MIDDLE mouse button positions the viewing window to the most recent
position which was left by an absolute motion (thumbing or undoing). The undo¬
ing position is initialized to the beginning of the scrollable object.
V microsystems
Revision A, of May 9, 1988
272 SunView 1 Programmer’s Guide
15.3. Creating, Destroying Scrollbars are created and destroyed with scrollbar_create () and
and Modifying scrollbar_destroy (). To take the simplest possible example, you get a
Scrollbars default scrollbar (vertical, on the left edge of the subwindow, etc.) by calling:
r -
\
Scrollbar bar;
bar = scrollbar_create(0);
_ >
You would destroy the scrollbar with the call:
f --
scrollbar_destroy(bar);
__
The appearance and behavior of a given scrollbar is determined by the values of
its attributes. Here’s an example of a non-default scrollbar:
/—
bar_l = scrollbar_create(
SCROLL_P LACEMENT,
SCROLL__EAST,
SCROLL_BUBBLE_COLOR,
SCROLL_BLACK,
SCROLL_BAR_DISPLAY_LEVEL,
SCROLL__ACTI VE,
SCROLL_BUBBLE_DISP LAY_LEVEL,
SCROLL__ACTIVE,
SCROLL_DIRECTION,
SCROLLJVERTICAL,
SCROLLJTHICKNESS,
20,
SCROLL_BUBBLE_MARGIN,
4,
0),
s.
In the above call, setting SCROLL_PLACEMENT to SCROLL_EAST will cause
the scrollbar to appear on the right edge of the subwindow. The scrollbar will be
20 pixels wide with a black bubble 4 pixels from each edge of the bar. The bar
and bubble will be shown only when the cursor is in the scrollbar.
You can modify and retrieve the attributes of a scrollbar with the two routines:
scrollbar_set(scrollbar, attributes)
Scrollbar scrollbar;
<attribute-list> attributes;
caddr_t
scrollbar_get(scrollbar, attribute)
Scrollbar scrollbar;
Scrollbar_attribute attributes;
If the scrollbar parameter is NULL, scrollbar_get () returns 0.
SCROLL_RECT, SCROLLJTHICKNESS, SCROLL_HEIGHT and
SCROLL_WIDTH do not have valid values until the scrollbar is passed into the
subwindow. As a work-around for this problem, the special symbol
SCROLLBAR has been provided. You can determine the default thickness of a
scrollbar before it has been attached to a subwindow with the call:
#sun
xr microsystems
Revision A, of May 9, 1988
Chapter 15 — Scrollbars 273
f
thickness = (int) scrollbar_get(SCROLLBAR, SCROLL_THICKNESS) ;
J
This convention is currentiy only implemented for SCROLL_THlCKNESS.
If you set the SCROLL_THiCKNESS attribute then you must also set the
SCROLL_DIRECTlON of the scrollbar, since the dimension of the scrollbar that
is altered by SCROLL_THICKNESS depends on the orientation of the scrollbar.
The figures on the next page show some of the attributes controlling the visual
appearance of a scrollbar. 89 Figure 15-2 illustrates the attributes that control the
scrollbar appearance. Figure 15-3 illustrates the attributes that control the
scrollbar placement.
89 For a complete list of the scrollbar attributes see the Scrollbar Attributes table in Chapter 19, SunView
Interface Summary.
Revision A, of May 9, 1988
274 SunView 1 Programmer’s Guide
Figure 15-2 Attributes Controlling Scrollbar Appearance
Scrollbar Attributes
SCROLL_RIGHT
SCROLL.THICKNESS
SCROLL_BAR_C0L0R
SCROLL.BLACK
SCROLL_VHITE
Page Button Attributes
SCROLL_PAGE_BUTTONS: TRUE or FALSE
SCROLL_PAGE_BUTTON_LENGTH
Bubble Attributes:
SCROLL_BUBBLE_HARGIN
SCR0LL_BUBBLE_C0L0R
■ SCROLL.BLACK
n SCROLI_GREY
Figure 15-3 Scrollbar Placement Attributes
SCROLL_DIRECTION:
SCROLL VERTICAL SCROLL HORIZONTAL
I
§sun
Xr microsystems
Revision A, of May 9, 1988
Chapter 15 — Scrollbars 275
15.4. Programmatic
Scrolling
To scroll to a given location from your program, call:
scrollbar_scroll_to(scrollbar, new_view_start)
Scrollbar scrollbar;
long new_view_start;
This routine saves the current value of SCROLL_viEW_START as
SCROLL_LAST_VIEW_START, sets SCROLL_VIEW_START to the value
passed in as new_view_start, and posts a scroll event to the scrollbar’s
client (i.e. the canvas, panel or text subwindow) using the Notifier. This has the
same effect as if the user had requested a scroll to new_view_start.
Revision A, of May 9,1988
The Selection Service
--
16
The Selection Service. 279
16.1. Getting the Primary Selection
16.2. Setting the Primary Selection
280
280
The Selection Service
The Selection Service provides for flexible communication among window appli¬
cations. You can use the Selection Service to query and manipulate the selec¬
tions the user has made.
This chapter gives only the simplest example of using the Selection Service. To
find out more about the Selection Service and the other functionality it provides,
refer to Chapter 9 of the SunView 1 System Programmer’s Guide.
The definitions necessary to use the Selection Service are found in the include
file <suntool/seln .h>.
Xr microsystems
279
Revision A, of May 9, 1988
280 SunView 1 Programmer’s Guide
16.1. Getting the Primary The primary selection is the selection made by the user without holding down
Selection any of the function keys, and is indicated with reverse-video highlighting on the
screen.
The routine below is taken from the program filer, listed in Appendix A. It
retrieves the primary selection by first asking the Selection Service which win¬
dow has the primary selection, then asking that window for the characters that
are in the selection, saving them in a static buffer, and returning a pointer to that
buffer:
#define <suntool/seln.h>
#define MAX_FILENAME_LEN 256
char *
get_selection ()
{
static char filename[MAX_FILENAME_LEN];
Seln_holder holder;
Seln_request ^buffer;
holder * seln_inquire(SELNJPRIMARY);
buffer = seln_ask(&holder, SELN_REQ_CONTENTS_ASCII, 0, 0);
strncpy(filename,
buffer->data + sizeof(Seln_attribute),
MAX_FILENAME_LEN);
return (filename);
}
_ )
This example has been kept simple by removing error checking. The code relies
on the fact that if there is no primary selection, or the Selection Service process is
not running, or the holder of the primary selection failed to returned the selection
string, then the buffer returned by seln_ask () will have an empty string for
the selection characters.
The routine also assumes that the selection will be no more than 256 characters
long. seln_ask () will handle selections of up to about 2000 characters. To
find out how to handle arbitrarily large selections, or selections other than the pri¬
mary selection, refer to the SunView 1 System Programmer’s Guide.
16.2. Setting the Primary
Selection
For an example of a program which sets, and responds to queries about, the
selection, see selndemo, in Chapter 9 of the SunView 1 System Programmer’s
Guide.
XT microsystems
Revision A, of May 9,1988
The Notifier
The Notifier... 283
Header Files. 283
Related Documentation. 283
17.1. When to Use the Notifier. 285
17.2. Restrictions. 285
Don’t Call.... 285
Don’t Catch.... 286
17.3. Overview... 287
How the Notifier Works. 287
Client Handles. 287
Types of Interaction. 287
17.4. Event Handling. 288
Child Process Control Events. 288
“Reaping” Dead Processes. 288
Results from a Process. 289
Input-Pending Events (pipes). 290
Example: Reading a Pipe. 290
Closing the Pipe. 291
Signal Events. 291
A signal () Replacement for Notifier Compatibility . 291
Example: Writing to a Pipe. 292
Asynchronous Event Handling. 293
Timeout Events. 294
Example: Periodic Feedback. 294
Polling. 295
Checking the Interval Timer. 296
Turning the Interval Timer Off. 296
17.5. Interposition. 296
How Interposition Works. 296
Monitoring a Frame’s State. 297
Example: Interposing on Open/Close. 297
Discarding the Default Action. 299
Interposing on Resize Events. 299
Example: resize_demo . 299
Modifying a Frame’s Destruction. 299
Destroy Events. 300
Checking. 300
Destruction. 300
A Typical Destroy Handler. 300
Example: Interposing a Client Destroy Handler. 301
17.6. Porting Programs to SunView. 303
Explicit Dispatching. 303
Implicit Dispatching. 303
Getting Out. 304
17.7. Error Handling. 305
Error Codes... 305
Handling Errors. 305
Debugging. 306
NOTIFY_ERROR_ABORT . 306
Stop in notify_j?error () or fprintf(3S). 306
notify_dump. 306
The Notifier
The Notifier is a general-puipose mechanism for distributing events to a collec¬
tion of clients within a process. It detects events in which its clients have
expressed an interest, and dispatches these events to the proper clients, queuing
client processing so that clients respond to events in a predictable order.
An overview of the notification-based model is given in Chapter 2, The SunView
Model.
To encourage the porting of existing applications, the Notifier has provisions to
allow programs to run in the Notifier environment without inverting their control
structure. See Section 17.6, Porting Programs to SunView.
Header Files The definitions for the Notifier are contained in the file
<sunwindow/notif y. h>, which will be included indirectly when you
include <suntool/sunview .h>.^°
Related Documentation This chapter will suffice for the majority of SunView applications. See the
chapters titled Advanced Notifier Usage and The Agent and Tiles in the Sun¬
View 1 System Programmer’s Guide for more information on the Notifier and
SunView’s usage of it. When looking up Notifier-related information, look first
in the index to this book, then in the index to the SunView 1 System
Programmer’s Guide.
Summary Listing and Table To give you a feeling for what you can do with the Notifier, the following page
contains a list of the available Notifier functions. Many of these are discussed in
the rest of this chapter and elsewhere (use the Index to check). All are briefly
described with their arguments in the Notifier Functions table beginning on page
343 in Chapter 19, SunView Interface Summary.
90 For those programmers utilizing the Notifier outside of SunView (a perfectly reasonable thing to do), the
code that implements the Notifier is found in /usr/lib/libsunwindow. a.
Xr microsystems
283
Revision A, of May 9, 1988
284 SunView 1 Programmer’s Guide
Notifier Functions
notify_default_wait3(client, pid, status*, rusage)
notify_dispatch()
notify_do_dispatch()
notify_interpose_destroy_func(client, destroy_func)
not if y__interpose_event__f unc (client, event_func, type)
notify_itimer_value(client, which, value)
notify_next_destroy_func(client, status)
notify_no_dispatch()
notify_j?error (s)
notify_set_destroy_func(client, destroy_func)
notify_set_exception_func(client, exception__func, fd)
notify_set_input__func (client, input__func, fd)
notify_set_itimer_func(client, itimer_func, which, value, ovalue)
notify_set_signal_func (client, signal__func, signal, when)
notify_start()
notify_stop()
notify_set_output_func(client, output_func, fd)
notify_set_wait3__func (client, wait3_func, pid)
notify_veto_destroy(client)
Revision A, of May 9, 1988
Chapter 17 — The Notifier 285
17.1. When to Use the
Notifier
17.2. Restrictions
Don’t Call...
signal(3)
sigvec(2)
setitimer(2)
alarm(3)
getitimer(2)
wait 3(2)
Since the Notifier is used by the SunView libraries, any program that uses Sun-
View implicitly uses the Notifier. You will have to use the Notifier explicitly if
you want to do any of the following:
a Catch signals, e.g., SIGCONT.
□ Notice state changes in processes that your process has spawned, e.g., a child
process has died.
□ Read and write through file descriptors, e.g., using pipes.
□ Receive notification of the expiration of an interval timer, e.g., so that you
can provide some blinking user feedback.
□ Extend, modify or monitor SunView Notifier clients, e.g., noticing when a
frame is opened, closed or about to be destroyed.
□ Use a non-notification-based control structure while running under Sun¬
View, e.g., porting programs to SunView.
The Notifier imposes some restrictions on its clients which designers should be
aware of when developing software to work in the Notifier environment. These
restrictions exist so that the application and the Notifier don’t interfere with each
other. More precisely, since the Notifier is multiplexing access to user process
resources, the application needs to respect this effort so as not to violate the shar¬
ing mechanism.
Assuming an environment with multiple clients with an unknown notifier usage
pattern, you should not use any of the following system calls or C library rou¬
tines: 91
The Notifier is catching signals on the behalf of its clients. If you set up your
own signal handler over the one that the Notifier has set up then the Notifier will
never notice the signal.
The same applies for sigvec(2) as does for signal(3), above.
The Notifier is managing two of the process’s interval timers on the behalf of its
many clients. If you access an interval timer directly, the Notifier could miss a
timeout. Use notif y_set_itimer_func () instead of setitimer(2).
Because alarm(3) sets the process’s interval timer directly, the same applies for
alarm(3) as does for setitimer(2), above.
When using a notifier-managed interval timer, you should call
notify_itimer_value () to get its current status. Otherwise, you can get
inaccurate results.
The Notifier notices child process state changes on behalf of its clients. If you do
your own wait 3(2), then the notifier may never notice the change in a child
91 A future release may provide modified versions of some of these forbidden routines that will allow their
use without restriction. However, the restrictions described in Don't Catch. .below, will continue to be
germane. A signal () Replacement for Notifier Compatibility , in Section 17.4, provides a code patch for
programs that catch signals.
17.1. When to Use the
Notifier
17.2. Restrictions
Don’t Call...
signal(3)
sigvec(2)
setitimer(2)
alarm(3)
getitimer(2)
wait 3(2)
Revision A, of May 9,1988
286 SunView 1 Programmer’s Guide
wait(2)
ioctl(2) (..., FIONBIO,...)
ioctl(2) (..., FIOASYNC,...)
system(3)
Don’t Catch...
SIGALRM
SIGVTALRM
SIGTERM
SIGCHLD
SIGIO
SIGURG
process or you may get a change of state for a child process in which you have no
interest. Use notify_set_wait3_func () instead of wait3(2).
The same applies for wait(2) as does for wait3(2), above.
This call sets the blocking status of a file descriptor. The Notifier needs to know
the blocking status of a file descriptor in order to determine if there is activity on
it f cntl(2) has an analogous request that should be used instead of ioctl(2).
This call controls a file descriptor’s asynchronous io mode setting. The Notifier
needs to know this mode in order to determine if there is activity on it
f cnt 1(2) has an analogous request that should be used instead of ioct 1(2).
In the SunOS, this function calls signal(3) and wait(2). Hence you should
avoid using this for the reasons mentioned above. Calls to system(3) should be
replaced with something like the following.
/-——-\
if((pid = vfork()) == 0) {
(void) execl(”/bin/sh", "sh" f "-c", str f (char *)0);
_exit(127);
}
notify__set_wait3_func (me, my_handler, pid);
Clients should not have to catch any of the following signals. If you are, then
you are probably also making one of the forbidden calls described above. You
might also be utilizing the Notifier inappropriately if you think that you have to
catch any of these signals. The Notifier catches these signals itself under a
variety of circumstances:
Caught by the Notifier’s interval timer manager. Use
notif y_set_itimer_func () instead.
The same applies for SIGVTALRM as does for SIGALRM above.
Caught by the Notifier so that it can tell its clients that the process is going away.
Use not if y_set_destroy_f unc () if that is why you are catching
SIGTERM.
Caught by the Notifier so that it can do child process management Use
notify_set_wait3_func () instead.
Caught by the Notifier so that it can manage its file descriptors that are running in
asynchronous io mode. Use notify_set_input_f unc () 92 or
notif y_set_output_func () if you want to know when there is activity
on your file descriptor.
Caught by the Notifier so that it can dispatch exception activity on a file descrip¬
tor to its clients. Use notif y_set_exception_func () if you are looking
for out-of-band communications when using a socket.
92 Do not use a NULL client handle when you use not i f y_set_input_f unc () or the Notifier will go
into an infinite loop.
wait(2)
ioctl(2) (..., FIONBIO,...)
ioct 1(2) (..., FIOASYNC,...)
system(3)
Don’t Catch...
SIGALRM
SIGVTALRM
SIGTERM
SIGCHLD
SIGIO
SIGURG
Revision A, of May 9,1988
Chapter 17 — The Notifier 287
If you think you have to catch one of these signals, then be sure to use
notify_set_signal_func().
17.3. Overview
How the Notifier Works Before it can receive events, a client must advise the Notifier of the types of
events in which it is interested. It does this by registering an event handler func¬
tion (which it must supply) for each type of event in which it is interested. When
an event occurs, the Notifier calls the event handler appropriate to the type of
event.
Figure 17-1 shows an overview of how the notification mechanism works.
Figure 17-1 Overview of Notification
— -> Client registers event proc at initialization time
-=► Notifier calls back to client when event received
Client Handles The Notifier uses a client handle as the unique identifier for a given client. The
Notifier, without interpreting the client handle in any way, uses it to associate
each event with the event handler for a given client.
The only requirement for a client handle is that it must be unique (within a pro¬
cess). Since a program text address or the address of an allocated data block are
guaranteed to be unique, they can be used. Since stack addresses are not in gen¬
eral guaranteed to be unique they should not be used. Internally, SunView uses
the object handles returned from window_create () as notifier client handles.
Types of Interaction Client interaction with the Notifier falls into the following functional areas:
□ Event handling — A client may receive events and respond to them via
event handlers. Event handlers do the bulk of the work in the Notifier
environment. The various types of events are in Section 17.4, Event Han¬
dling.
□ Interposition — A client may request that the Notifier install a special type
of event handler (supplied by the client) to be inserted (or interposed) ahead
of the current event handler for a given type of event and client. This allows
clients to screen incoming events and redirect them, and to monitor and
change the status of other clients. Examples of interposition may be found
below under Monitoring a Frame’s State.
microsystems
Revision A, of May 9,1988
288 SunView 1 Programmer’s Guide
□ Notifier control — A client may exercise control over when dispatching of
events occurs. See Section 17.6, Porting Programs to SunView.
17.4. Event Handling This section describes how to be notified of UNIX-related events and notifier sup¬
ported destroy events (see Chapter 6, Handling Input, for a description of
SunView-defined events). UNIX events are low-level occurrences that are mean¬
ingful at the level of the operating system. These include signals (software inter¬
rupts), input pending on a file descriptor, output completed on a file descriptor,
tasks associated with managing child processes, and tasks associated with
managing interval timers.
A client establishes an interest in a certain type of event by registering an event
handler procedure to respond to it. The event handler for a given type of event
has a mandatory calling sequence, as described below. All event handlers return
a value of either notify_done or notify_ignored depending on whether
the event was acted on in some way or failed to provoke any action, respectively.
When registering an event handler, the registration procedure returns a pointer to
the function that was in place previous to the current call. On initialization, the
Notifier sets up its internal tables by registering “dummy” functions as place¬
holders. These dummy functions are no-op functions with no harmful side-
effects. The first time a client registers a given type of event handler, it will
receive a pointer to a “dummy” function.
The following sections describe common usages of various types of events.
Child Process Control Events Let’s say that you want to fork a process to perform some processing on your
behalf. UNIX requires that you perform some housekeeping of that process. The
minimum housekeeping required is to notice when that process dies and “reap”
it. You can register a wait3 event handler, 93 which the Notifier will call when¬
ever a child process changes state (e.g. dies), by calling:
Notify_func
notify_set__wait3_func (client, wait3_func, pid)
static Notify_client client;
Notify_f unc wait3_func;
int pid;
“Reaping” Dead Processes Clients using child process control which simply need to perform the required
reaping after a child process dies can use the predefined
notif y_def ault_wait3 () as their wait3 event handler. For example:
93 The name wait3 event originates from the wait 3(2) system call.
microsystems
Revision A, of May 9, 1988
Chapter 17 — The Notifier 289
*
Results from a Process
-s
♦include <sunwindow/notify.h>
static int my__client__object;
static Notify_client *me = &my_client__object;
int pid;
if ((pid = my_fork()))
(void) notify__set_wait3_func (me, notify__default_wait3,
pid) ;
/* Start dispatching events */
(void) notify_start();
v_/
This is sufficient to have your child process reaped on its death. The Notifier
automatically removes a dead process’s wait3 event handler from its internal data
structures.
NOTE The use of me as a client handle is arbitrary, but illustrates one method of gen¬
erating a unique client handle.
A more interesting application might actually receive some results from the pro¬
cess it forked. In this case, the application would supply its own wait3 event
handler 94 . For example:
—
♦include <sunwindow/notify.h>
♦include <sys/wait.h>
♦include <sys/time.h>
♦include <sys/resource.h>
static Notify_value my_wait3_handler();
/* Register a wait3 event handler */
(void) notify_set_wait3__func (me, my__wait3_handler, pid) ;
/* Start dispatching events */
(void) notify_start();
static Notify_value
my_wait3_handler(me, pid, status, rusage)
Notify__client me;
int pid;
union wait *status;
struct rusage *rusage;
if (WIFEXITED(^status)) {
/* Child process exited with return code */
my_return_code_handler (me, statu s->w__ret code) ;
/* Tell the notifier that you handled this event */
return (NOTIFY__DONE) ;
}
/* Tell the notifier that you ignored this event */
return (NOTIFY_IGNORED);
V_ )
94 See the wait (2) manual page for details of union wait and struct rusage.
microsystems
Revision A, of May 9, 1988
290 SunView 1 Programmer’s Guide
Input-Pending Events (pipes) A program may need to know when there is input pending on a file descriptor—
for instance, on one end of a pipe. Let’s extend our previous example a bit to
include reading data from a pipe connected to a process that we have forked.
You can register an input-pending event handler which the Notifier will call
whenever whenever there is input pending on a file descriptor 95 by calling:
Notify_func
notify_set_input_func(client, input_func, fd)
Notify_client client;
Notify_func input_func;
int fd;
The calling sequence for the input_f unc () you supply is as follows:
Not if y__value
input__func (client, fd)
Not if y__client client ;
int fd;
Example: Reading a Pipe
--— \
♦include <sunwindow/notify.h>
static Notify_value my_pipe_reader();
int fildes[2];
/* Create a pipe */
if (pipe(fildes) == -1) {
perror("pipe");
exit (1);
}
/* Register an input-pending event handler */
(void) notify_set_input_func(me, my__pipe_reader, fildes[0]);
... do fork and dispatching from wait 3 event example ...
... do fork and dispatching from wait 3 event example ...
static Notify_value
my_pipe_reader(me, fd)
Notify_client me;
int fd;
/* Read the pipe (fd) */
/* Tell the notifier that the input event is handled */
return (NOTIFY_DONE);
'
In the above example, the application uses the Notifier to read from the pipe
because it doesn’t want to block on input pending on the pipe. In the case of a
SunView program, the program wants to return back to the Notifier’s central
dispatching loop so that the user can interact with the window while waiting for
input to become available on the pipe.
95 The file descriptor can be in blocking or non-blocking mode, or in asynchronous mode; the Notifier
handles both as long as you have used f cnt 1(2) to set the modes.
Xr microsystems
Revision A, of May 9,1988
Chapter 17 — The Notifier 291
When you close any file descriptor that has been registered with the Notifier you
should unregister it. To do this, call notif y_set_input_func () with a
notify_func of NOTIFY_FUNC_NULL. 96 ~
Signals are UNIX software interrupts. The Notifier multiplexes access to the
UNIX signal mechanism. A client may ask to be notified that a UNIX signal
occurred either when it is received (asynchronously) and/or later during normal
processing (synchronously).
Clients may define and register a signal event handler to respond to any UNIX
signal desired. However, many of the signals that you might catch in a tradi¬
tional UNIX program may be being caught for you by the Notifier (see Don’t
catch above).
CAUTION Clients of the Notifier must not directly catch any UNIX signals using sig¬
nal (3) or sigvec(2). Regardless of whether clients choose synchronous or
asynchronous signal notification, they must use the signal event mechanism
described in this section. See Section 17.2, Restrictions.
You can register a signal event handler which the Notifier will call whenever a
signal has been caught by calling:
Notify_func
not if y_set_signal__func (client, signal_func, signal, when)
Notif y__client client ;
Notify_func signal_func;
int signal;
Notify_signal_mode when;
when can be either NOTIFY_SYNC or NOTIFY_ASYNC. NOTIFY_SYNC
causes notification during normal processing, that is, the delivering of the signal
is delayed, so that your program doesn’t receive it at an arbitrary time.
N0TIFY_ASYNC causes notification immediately as the signal is received, —
this mode mimics the UNIX signal(3) semantics.
You should rewrite applications to use notif y_set_signal_func ().
However, the Notifier routine notif y_set_signal_f unc () does not fully
emulate the signal(3) function. It does not handle errors the same way sig-
nal(3) does. Errors from signal(3) are indicated by a -1 return value, and
the value of errno is set to EINVAL.
The errors for notif y_set_signal_f unc () are not communicated back to
the caller, but error messages are printed. For example, if the signal number is
not valid, the Notifier prints
but its return value indicates success; the signal(3) system call does not print a
message, but returns -1 and sets errno to EINVAL. As another example, if
96 This method of passing in a NOTIFY_FUNC_NULL to unregister an event handler from the Notifier
works for any type of event
/ - — . .
Bad signal number
v '• • - v - •• •
A signal () Replacement for
Notifier Compatibility
Closing the Pipe
Signal Events
Revision A, of May 9,1988
292 SunView 1 Programmer’s Guide
SIGKILL or SIGSTOP are ignored or a handler supplied, the Notifier prints
-.
Notifer assertion botched: Unexpected error: sigvec
v . ’ • ■ •- - '• • ■■■■■■ _:_ : " _
but its return value indicates success, while sign a 1(3) does not print a message,
returns value of -1, and sets errno to EINVAL.
The work-around is to use the following replacement function for the C library
version of signal(3). This code converts signal () calls into
notify_set_signal_func () calls. Explicitly loading this code will over¬
ride the loading of the C library’s version of signal (). This approach works
only if all the signal handlers registered by signal () only look at the first
argument passed to them when a signal is received. Also, no Notifier client han¬
dle may be a small integer.
< '
♦include <sunwindow/notify.h>
♦include <errno.h>
int (*
signal (sig, func)) ()
int sig,(*func)();
if ( (sig <1 || sig > NSIG) ||
(sig — SIGKILL || sig — SIGSTOP) ) {
errno - EINVAL;
return(BADSIG);
}
if (sig == SIGCONT && func == SIG_IGN) {
errno = EINVAL;
return(BADSIG);
}
return ( (int (*) ())notify_set_signal_func(sig, func,
sig, NOTIFY_ASYNC));
s_ )
Example: Writing to a Pipe Let’s extend our on-going example by writing on the pipe. Writing to a pipe that
has no process at the other end to receive the message causes a SIGPIPE to be
generated by UNIX. By default, an uncaught SIGPIPE causes a premature pro¬
cess termination. So, we are going to catch SIGPIPE so that our process
doesn’t get killed if we start a process that dies . 97
97 We are glossing over the part about actually writing to the pipe. If we wanted to write something to the
pipe and then get some notification about when the write had actually completed (i.e., the other process had read
it) we would use the not if y_set_output_f unc () call. The calling sequences for this routine and its
event handler are exactly the same as those for not i f y_set_input_f unc () (previously described).
m sun
xr microsystems
Revision A, of May 9, 1988
Chapter 17 — The Notifier 293
f —
♦include <sunwindow/notify.h>
♦include <signal.h>
\
static Notify_value my_sigpipe_handler();
... do pipe from input-pending example ...
... do notify set_input_func from input-pending example ...
... do fork from wait 3 event example ...
/* Register a signal event handler */
(void) notify set signal__func (me, my_sigpipe__handler,
SIGPIPE, NOTIFY_ASYNC) ;
/* Write a message on the pipe */
/* Start dispatching events */
(void) notify_start();
static Notify__value
my sigpipe_handler(me, signal, when)
Notify_client me;
int signal;
Notify_signal__mode when;
/*
* This is a no-op function meant only
* being killed because we didn't have
*/
return (NOTIFY_I GNORED);
-——
to prevent us from
a SIGPIPE handler.
_>
This example wouldn’t actually show my_sigpipe_handler () being called
unless you set up the child process to die right away.
An asynchronous signal notification can come at any time (unless blocked using
sigblock(2)). This means that the client can be executing code at any arbi¬
trary place. Great care must be exercised during asynchronous processing.
It is rarely safe to do much of anything in response to an asynchronous signal.
Unless your program has taken steps to protect its data from asynchronous
access, the only safe thing to do is to set a flag indicating that the signal has been
received.
When in an asynchronous signal event handler, the signal context and signal code
is available from the follow routines:
int
notify_get_signal_code()
struct sigcontext *
notify_get_signal_context ()
The return values of these routines are undefined if called from a synchronous
signal event handler.
microsystems
Revision A, of May 9,1988
294 SunView 1 Programmer’s Guide
Timeout Events
Example: Periodic Feedback
A client may require notification of an expired timer based on real time (approxi¬
mate elapsed wall clock time; IT IMER_REAL) or on process virtual time (CPU
time used by this process; ITIMER__VIRTUAL). To receive this type of
notification, the client must define and register a timeout event handler.
Notify_func
notify_set_itimer_func(client, itimer_func, which, value,
ovalue)
Notify_client client;
Notify_func itimer_func;
int which;
struct itimerval *value, *ovalue;
The semantics of which, value and ovalue parallel the arguments to seti-
timer(2) (see the getitimer(2) manual page), which is either
ITIMER_REAL or ITIMER_VIRTUAL.
As an example, we want to provide some form of blinking feedback. We do this
by setting up an interval timer when we want to blink. We turn the internal timer
off when we no longer need the blinking. 98
98 This code segment should be wrapped in, say, a panel notify procedure, in order to be actually run.
Revision A, of May 9, 1988
Chapter 17 — The Notifier 295
-— >
#include <sunwindow/notify.h>
♦include <sys/time.h>
static int blinking__required; /* blinking desired */
static int blinking; /* blinking enabled */
♦define ITIMER_NULL ((struct itimerval *)0)
static Notify__value my_blinker () ;
if (blinking_required && !blinking) {
struct itimerval blink_timer;
/* Set up interval with which to RELOAD the timer */
blink_timer.it_interval.tv_usec = 0;
blink_timer.it_interval.tv_sec = 1;
/* Set up INITIAL value with which to SET the timer */
blink_timer. it__value. tv_usec = 0;
blink_timer. it_value .tv__sec = 1;
/* Turn on interval timer for client */
(void) notify_set__itimer_func (me, my__blinker,
ITIMER_REAL, &blink_timer, ITIMER_NULL);
blinking = 1;
} else if (!blinking_required && blinking) {
/* Turn off interval timer for client */
(void) notify_set_itimer__func (me, my_blinker,
ITIMER_REAL, ITIMER_NULL f ITIMER_NULL);
blinking = 0;
}
static Notify_value
my_blinker(me, which)
Notify__client me;
int which;
/* Do the blink */
return (N0TIFY_D0NE);
V_ )
Polling Interval timers can be used to set up a polling situation. There is a special
value argument to notif y_set_it imer_func () that tells the Notifier to
call you as often and as quickly as possible. This value is the address of the
following constant:
Struct itimerval NOTIFY_POLLING_ITIMER; /*{{0,1}, {0,1} }*/
This high speed polling can consume all of your machine’s available CPU time,
but may be appropriate for high speed animation. It is used in the program
spheres, which shows one way to convert and old SunWindows gfx subwindow-
based program to SunView. spheres is explained in Appendix C, Converting
SunWindows Programs to SunView, and is listed in full in in Appendix A, Exam¬
ple Programs.
#sun
\r microsystems
Revision A, of May 9, 1988
296 SunView 1 Programmer’s Guide
Checking the Interval Timer
The following function checks on the state of an interval timer by returning its
current state in the structure pointed to by value.
Notify_error
notify_itimer_value(client, which, value)
Notify_client client;
int which;
struct itimerval *value;
Turning the Interval Timer Off
If you specify an interval timer with its it_interval structure set to
{0, 0}, the Notifier flushes any knowledge of the interval timer after it delivers
the timeout notification. Otherwise, supplying a NULL interval timer pointer to
notif y_set_itimer_f unc () will turn the timer off.
17.5. Interposition
SunView window objects utilize the Notifier for much of their communication
and cooperation. The Notifier provides a mechanism called interposition, with
which you can intercept control of the internal communications within SunView.
Interposition is a powerful way to both monitor and modify window behavior in
ways that extend the functionality of a window object.
Interposition allows a client to intercept an event before it reaches the base event
handler. The base event handler is the one set originally by a client. The client
can call the base event handler before or after its own handling of the event, or
not at all. Clients may use interposition to monitor and filter events coming in to
an event handler and/or to modify a series of actions based on the results of some
calculation.
How Interposition Works
A client requests that the Notifier install an interposer function, supplied by the
client, for a specified client and type of event. When an event arrives, the
Notifier calls the function at the top of the wait list for that client and that type of
event. An interposed routine may (indirectly) call the next function in the inter¬
position sequence and receive its results.
Figure 17-2 illustrates the flow of control with interposition. Note that the inter¬
poser could have stopped the flow of control to the base event handler.
#sun
Xr microsystems
Revision A, of May 9,1988
Chapter 17 — The Notifier 297
Figure 17-2
Monitoring a Frame’s State
Example: Interposing on
Open/Close
Flow of Control in Interposition
You can notice when a frame opens or closes by interposing in front of the
frame’s client event handler. The client event handler is a SunView specific
event handler which is built on top of the Notifier’s general client event mechan¬
ism." To install an interposer call the following routine:
Notify_error
notify_interpose_event_func(client, event_func, type)
Notify_client client;
Notify_func event_func;
Notify__event_type type;
client must be the handle of the Notifier client in front of which you are inter¬
posing. In SunView, this is the handle returned from window_create () . 10 °
type is always NOTIFY_SAFE for SunView clients.
Let’s say that the application is displaying some animation, and wants to do the
necessary computation only when the frame is open. It can use interposition to
notice when the frame opens or closes.
The program spheres (which shows one way to convert an old SunWindows gfx
subwindow-based program to SunView) uses this technique to stop shading an
image when its frame is closed. It is explained in Appendix C, Converting
SunWindows Programs to SunView, and is listed in full in in Appendix A, Exam¬
ple Programs.
Another example appears on the following page. Note the the call to
notif y_next_event_f unc (), which transfers control to the frame’s client
event handler through the Notifier. notif y_next_event_f unc () takes the
same arguments as the interposer.
99 The stream of events sent to a client event handler is described in in Chapter 6, Handling Input.
100 It could also be the handle returned from the call to scrollbar create ().
sun Revision A, of May 9,1988
microsystems
298 SunView 1 Programmer’s Guide
♦include <suntool/sunview.h>
static Notify__value my_frame_interposer () ;
Frame frame;
/* Create the frame */
frame = window_create(0, FRAME,
0 );
/* Interpose in front of the frame's event handler */
(void) notify_interpose__event_func (frame,
my__frame_interposer, NOT I FY_S AFE) ;
/* Show frame and start dispatching events */
window_main___loop (frame) ;
static Notify__value
my_frame_interposer(frame, event, arg, type)
Frame frame;
Event *event;
Notify_arg arg;
Notify_event_type type;
int closed_initial, closed_current;
Notify__value value;
{
/* Determine initial state of frame */
closed_initial * (int) window_get(frame, FRAME_CLOSED);
/* Let frame operate on the event */
value = notify_next_event_func(frame, event, arg, type);
/* Determine current state of frame */
closed_current = (int) window_get(frame, FRAME_CLOSED);
/* Change animation if states differ */
if (closed__initial != closed_current) {
if (closed_current) {
/* Turn off animation because closed */
(void) notify_set_itimer_func(me, my_animation,
ITIMER_REAL, ITIMER_NULL, ITIMER_NULL);
} else {
/* Turn on animation because opened */
(void) notify__set__itimer_func (me, my_animation,
ITIMER_REAL, &NOTIFY_POLLING_ITIMER,
ITIMER_NULL);
}
}
return (value);
}
Xr microsystems
Revision A, of May 9, 1988
Chapter 17 — The Notifier 299
Discarding the Default Action
In the example on the preceding page, you wanted the base event handler to han¬
dle the event (so that the frame gets closed/opened). If the interposed function
replaces the base event handler, and you don’t want the base event handler to be
called at all, your interposed procedure should not call
not if y_next_event (). For example, your interposed function might han¬
dle scroll events itself, so you would not want the base event handler to perform
an additional scroll.
Interposing on Resize Events Another common use of interposition is to give your application more control
over the layout of its subwindows. The code is very similar. You call
notify_interpose_event_func () to interpose your event handler. In
the event handler, the following fragment could be used:
,
value = notify_next_event_func(frame, event, arg, type);
if (event_action(event) == WIN_RESIZE)
resize(frame);
return(value);
s- J
Let the default event handler handle the event, then check if the event is a resize
event. If so, call your own resize () procedure to lay out the subwindows.
NOTE
A WIN_RESIZE event is not generated until the frame is resized. If you want
your resize procedure to be called when the window first appears you must do so
yourself. This is different from a canvas with the CANVAS_RESIZE attribute
set, whose resize procedure is called the first time the canvas is displayed.
If the user manually adjusts subwindow sizes using [ Control 1 -middle mouse but¬
ton, no WIN_RESIZE event is generated. You can disallow subwindow resizing
by setting the FRAME_SubwiNDOWS_AD JUSTABLE attribute to FALSE.
Example: resize demo The program resize demo shows how to achieve more complex window layouts
than possible using window layout attributes. It is listed in Appendix A, Exam¬
ple Programs.
Modifying a Frame’s Suppose an application must detect when the user selects the ‘Quit’ menu item in
Destruction the frame menu, in order to perform some application-specific confirmation. We
have to interpose in front of the frame’s client destroy event handler using the
following routine.
Notify_error
notify_interpose_destroy__func (client, destroy_func)
Notify_client client;
Notify_func destroy_func;
First, however, you need to understand client destroy events.
Revision A, of May 9, 1988
300 SunView 1 Programmer’s Guide
Destroy Events
Checking
Destruction
A Typical Destroy Handler
The Notifier can tell each client to destroy itself. It is possible for a destroy event
handler to receive two calls concerning client destruction: one call may be a
status inquiry and the other a demand for termination. Destroy event handlers
use a status code to determine whether the caller demands actual termination
(DESTROY_CLEANUP or DESTROY_PROCESS_DEATH), or simply requires an
indication if it is feasible for the client to terminate at present
DESTROY_CHECKING).
If the status argument indicates an inquiry and the client cannot terminate at
present, the destroy event handler should call not if y_veto_destroy (),
indicating that termination would not be advisable at this time, and return nor¬
mally. If the status argument indicates an inquiry and the client can terminate
at present, then the destroy handler should do nothing; a subsequent call will tell
the client to actually destroy itself.
This veto option is used, for example, to give a text subwindow the chance to ask
the user to confirm the saving of any editing changes when quitting a tool.
If the status argument is not DESTROY_CHECKlNG then the client is being
told to destroy itself. If status is DESTROY_PROCESS_DEATH then the
client can count on the entire process dying and so should do whatever it needs to
do to cleanup its outside entanglements, e.g., update a file used by other
processes. Since the entire process is dying, one might choose to not release all
the resources used within the process, e.g., dynamically allocated memory.
However, if status is DESTROY_CLEANUP then the client is being asked to
destroy itself and be very tidy about cleaning up all the process internal resources
that it is using, as well as its outside entanglements.
A typical destroy handler looks like the following:
Notify_value
common_destroy__func (client f status)
Notify_client client;
Destroy_status status;
if (status == DESTROY_CHECKING) {
if (/* Don't want to go away now */)
notify_veto_destroy(client);
} else {
/* Always release external commitments */
if (status -- DESTROY_CLEANUP)
/* Conditionally release internal resources */
}
return (NOTIFY_DONE);
Nr microsystems
Revision A, of May 9,1988
Chapter 17 — The Notifier 301
Example: Interposing a Client
Destroy Handler
Now we can present the example of interposing in front of the frame’s client des¬
troy event handler. In addition to doing our own confirmation, we prevent dou¬
ble confirmation by suppressing the frame’s default confirmation.
Note that after having the destroy OK’d by the user, we call
notify_next_destroy_func () before returning. This allows other
subwindows to request confirmation.
The code appears on the following page.
W sun
\r microsystems
Revision A, of May 9, 1988
302 SunView 1 Programmer’s Guide
#include <suntool/sunview.h>
static Notify_value my_frame_destroyer();
/*
* Interpose in front of the frame's destroy event handler
*/
(void) notify__interpose_destroy_func (frame,
my_frame_destroyer) ;
/* Show frame and start dispatching events */
window_main_loop(frame);
static Notify_value
my_frame_destroyer(frame, status)
Frame frame;
Destroy_status status;
if (status — DE STROY_CHECKING) {
if (my internal state requires confirmation) {
/*
* Request confirmation from the user
* (see window_loop() in the index) .
*/
if ( destroy OK’d by user) {
/* Tell frame not to do confirmation */
window_set(frame, FRAME_NO_CONFIRM, TRUE, 0);
} else {
/*
* Tell the Notifier that the destroy has
* been vetoed.
*/
(void) notify_veto_destroy (frame) ;
/*
* Return now so that the destroy event
* never reaches the frame's destroy handler.
*/
return (NOTIFY_DONE);
}
} else {
/* Let frame do normal confirmation */
window_set (frame, FRAME_NO_CONFIRM, FALSE, 0) ;
}
}
/* Let frame get destroy event */
return (not if y__next_destroy_func (frame, status));
}
Xr microsystems
Revision A, of May 9, 1988
Chapter 17 — The Notifier 303
17.6. Porting Programs to Most programs that are ported to SunView are not notification-based. They are
SunView traditional programs that maintain strict control over the inner control loop.
Much of the state of such programs is preserved on the stack in the form of local
variables. The Notifier supports this form of programming so that you can use
SunView packages without inverting the control structure of your program to be
notification-based.
Explicit Dispatching The simplest way to convert a program to coexist with the Notifier is called
explicit dispatching. This approach replaces the call to
window_main_loop (), which usually doesn’t return until the application ter¬
minates, with the following bit of code:
r
♦include <suntool/sunview.h>
\
static int my_done;
extern Notify_error notify_dispatch()
/
/* Make the frame visible on the screen */
window_set(frame, WIN_SHOW, TRUE, 0);
while (!my_done) {
/* Dispatch events managed by
(void) notify__dispatch () ;
the Notifier */
}
v_
-j
notif y_dispatch () goes once around the Notifier’s internal loop,
dispatches any pending events, and returns. You should try to have
notif y_dispatch () called at least once every 1/4 second so that good
interactive response with SunView windows can be maintained.
The program bounce (which shows one way to convert an old Sun Windows gfx
subwindow-based program to SunView) uses explicit dispatching. It is
explained in Appendix C, Converting SunWindows Programs to SunView, and is
given in full in in Appendix A, Example Programs.
Implicit Dispatching Explicit dispatching is good when you are performing some computationally
intensive processing and you want to occasionally give the user a chance to
interact with your program. There is another method of interacting with the
Notifier that is useful when you simply want the Notifier to take care of its clients
and block until there is something of interest to you. This is called implicit
dispatching.
This time, we replace the call to window_main_loop () with the following
bit of code:
xr microsystems
Revision A, of May 9,1988
304 SunView 1 Programmer’s Guide
♦include <suntool/sunview.h>
static int my_done;
window_set(frame, WIN_SHOW, TRUE, 0) ;
/* Enable implicit dispatching */
(void) notify_do_dispatch();
while (!my_done) {
char c;
/* read allows implicit dispatching by Notifier */
if ((n = read(0/*stdin*/, &c, 1)) < 0)
perror("my_program");
}
S_/
not if y_do_dispatch () allows the Notifier to dispatch events from within
the calls to read(2) or select(2). The Notifier’s versions of read(2) and
select (2) won’t return until the normal versions would. They can block
exactly like the normal versions.
not if y_no_dispat ch () (it takes no arguments) prevents the Notifier from
dispatching events from within the call to read(2) or select(2).
Getting Out When you use either of these dispatching approaches, you will need to find out
when the frame is ‘Quit’ by the user, in order to know when to terminate your
program. To do so, interpose in front of the frame’s destroy event handler, as in
the previous section, so that you can notice when the frame goes away. At this
point you can call notif y_stop () to break the read(2) or select(2) out
of a blocking state.
NT microsystems
Revision A, of May 9,1988
Chapter 17 — The Notifier 305
17.7. Error Handling
Error Codes
Handling Errors
--— >
♦include <suntool/sunview.h>
static int my_done;
static Notify_value my_notice_destroy ();
/*
* Interpose in front of the frame's destroy event handler
*/
(void) notify__interpose_destroy_func (frame,
my_notice_destroy) ;
static Notify_value
my_notice_destroy(frame, status)
Frame frame;
Destroy_status status;
if (status !— DESTROY_CHECKING) {
/* Set my flag so that I terminate my loop soon */
my_done = 1; ,
/* Stop the notifier if blocked on read or select */
(void) notify_stop();
}
/* Let frame get destroy event */
return (not if y_next__destroy_func (frame, status));
s_ J
Every call to a notifier routine returns a value that indicates success or failure.
Routines that return an enumerated type called Notif y_error deliver
N0TIFY_0K (zero) to indicate a successful operation, while any other value
indicates failure. Routines that return function pointers deliver a non-null value
to indicate success, while a value of N0TIFY_FUNC_NULL indicates an error
condition.
When an error occurs, the global variable not if y_errno describes the failure.
The Notifier sets not if y_errno much like UNIX system calls set the global
errno; that is, the Notifier only sets not if y_errno when it detects an error
and does not reset it to notify_OK on a successful operation. A table in the
SunView 1 System Programmer’s Guide lists each possible value of
notify_errno and its meaning.
Most of the errors returned from the Notifier indicate a programmer error, e.g.,
the arguments are not valid. Often the best approach for the client is to print a
message if the return value is non-zero and exit. The procedure
notif y_perror () takes a string which is printed to stderr, followed by a
colon, followed by a terse description of notif y_errno. This is done in a
manner analogous to the UNIX perr or(3) call.
microsystems
Revision A, of May 9,1988
306 SunView 1 Programmer’s Guide
Debugging Here are some debugging hints that may prove useful when programming:
NOT IF Y_ERROR_ABORT Setting the environment variable NOTlFY_ERROR_ABORT to YES will cause
the Notifier to abort with a core dump when the Notifier detects an error. This is
useful if there is some race condition that produces notifier error messages that
you are having a hard time tracking down.
Stop in not if y_j>error () If you are getting notifier error messages, but don’t know from where, try putting
or fprintf (3S) a break point on the entry to either not if y_perror () or f printf (3S).
Trace the stack to see what provoked the message.
not if y_dump The following call can be made from the debugger or your program to dump a
printout of the state of the Notifier:
void
notify_dump(client, type, file)
Notify_client client;
int type;
FILE *file;
The state of client is dumped to file based on the value of type. If
client is 0 then all clients are dumped. If type is 1 then all the registered
event handlers are dumped. If type is 2 then all the events pending for delivery
are dumped. If type is 3 then both the registered event handlers and the events
pending for delivery are dumped. If f ile is 1 then stdout is assumed. If f ile
is 2 then stderr is assumed. To be able to call notif y_dump () you need to
reference it from some place in your program so that it gets loaded into your
binary.
Revision A, of May 9,1988
Attribute Utilities
Attribute Utilities. 309
18.1. Character Unit Macros. 309
18.2. Creating Reusable Attribute Lists. 310
Default Attributes. 311
18.3. Maximum Attribute List Size. 311
Attribute Utilities
This chapter describes macros and functions that are provided as utilities to be
used with attributes.
18.1. Character Unit By default in SunView, coordinate specification attributes interpret their values
Macros in pixel units. For applications that don’t make heavy use of images, it is usually
more convenient to specify positions in character units — columns and rows
rather than xs and ys. To this end two macros ATTR_ROW () and ATTR_COL ()
are provided, which interpret their arguments as rows or columns, respectively,
and convert the value to the corresponding number of pixels, based on the
subwindow’s font, as specified by WIN_F0NT. ATTR_ROW () and
ATTR__COL () take as arguments any expression yielding an integer. The use of
these macros as an operand in an expression is restricted to adding a pixel offset
(e.g., ATTR_ROW(5) + 2). Examples of legal and illegal usage are given in the
table below.
Table 18-1
Example uses of the ATTR_ROW() and ATTR_COL() macros
Attribute/Value
PANE L_ITEM_X, 5
PANEL_ITEM_Y, 10
PANEL_ITEM_X, ATTR_COL(5)
PANEL_ITEM__X, ATTR_COL (-5)
PANEL_ITEM_X, ATTR_COL (5+2)
PANEL_ITEM_X, ATTR_COL (5) +2
PANEL__I TEM_X, ATTR_COL (5) -1
PANEL_I TEM_Y, ATTR_ROW (10)
PANEL_ITEM_Y, ATTR_ROW (-10)
PANEL_ITEM_Y, ATTR_ROW (10+2)
PANEL_ITEM_Y, ATTR_ROW(10)+2
PANEL_ITEM_Y, ATTR_ROW(10)-1
PANEL_ITEM_X, ATTR_COL(10)+ATTR_COL(2)
PANEL_ITEM_X f 2*ATTR COL(10)
Interpretation
5 pixels from left
10 pixels from top
column 5
column -5
column 7
2 pixels to right of col 5
1 pixel to left of col 5
row 10
row -10
row 12
2 pixels down from row 10
1 pixel up from row 10
illegal
illegal
NOTE ATTR_ROW () and ATTR_COL () treat their arguments as character positions
rather than lengths. In other words, when you use attr_row(5), the pixel
value that is computed includes the top margin. Similarly, the pixel value com¬
puted using ATTR_COL(5) includes the left margin.
309 Revision A, of May 9, 1988
310 SunView 1 Programmer’s Guide
These macros can be used with the panel attributes or the window attributes such
as WIN_X, WIN_HEIGHT, etc.
Both the attributes and the ATTR_ROW () and ATTR_COL () macros are zero-
based — that is, the first row is row zero.
If you want to use lengths rather than positions, you can use the alternate macros
ATTR_ROWS () and ATTR_COLS (). Examples of the differences between the
character position and length macros are given in the table below.
Table 18-2 Example uses of the ATTR_ROWS() and ATTR_COLS() macros
Attribute/Value
Interpretation
WIN_WIDTH, ATTR_COL(80)
80 characters wide + left margin
WIN_WIDTH, ATTR_COLS(80)
exactly 80 characters wide
WIN_HEIGHT, ATTR_ROW(24)
24 lines high + top margin
WIN_HEIGHT, ATTR_ROWS(24)
exactly 24 lines high
PANEL_ITEM_X, ATTR_COL(5)
col 5 (left margin + 5 character widths)
PANEL_ITEM_X, ATTR_COLS(5)
5 character widths from the left edge
PANEL_ITEM_Y, ATTR_ROW(5)
row 5 (top margin + 5 row heights)
PANEL_ITEM_Y, ATTR_ROWS(5)
5 row heights from the top edge
18.2. Creating Reusable You may want to create an attribute list that can be passed to different routines.
Attribute Lists You can do this either by creating the list explicitly, or by using the routine
attr create list().
To create an attribute list explicitly, define a static array of char *, which is
initialized (or later filled in with) the desired attribute/value pairs. Note that
non-string values must be coerced to type char *:
r
static char ^attributes[] = {
(char*)PANEL_LABEL_STRING,
"Name: ",
(char*)PANEL_VALUE,
"Goofy ",
(char*)PANEL_NOTIFY_PROC,
(char *)name_item_proc.
0 }
V__ _
__y
To make an attribute list dynamically, use:
Attr_avlist
attr_create_list(attributes)
<attribute-list> attributes;
attr_create_list () allocates storage for the list it returns. It is up to you
to free this storage when no longer needed, as in:
microsystems
Revision A, of May 9,1988
Chapter 18 — Attribute Utilities 311
Attr_avlist list;
list = attr_create_list(PANEL_LABEL_BOLD, TRUE, 0);
free(list);
--- t
The free () procedure is the standard UNIX free(3) routine.
Default Attributes The code below shows how to use attr_create_list () in conjunction
with the attribute ATTR_LIST to support default attributes in a panel.
/—
int
Panel_item
text_proc() f name_proc();
name_item, address_item;
\
Pixfont
*big_font, *small_font;
Attr_avlist
defaults;
defaults =
attr__create_list (
PANEL_SHOW_I TEM,
FALSE,
PANE L__LABE L__F ON T,
big_font.
PANEL_VALUE_FONT,
small_font.
PANEL NOTIFY PROC,
0);
text_j?roc.
name_ji.tem =
panel_create_item(PANEL_TEXT,
ATTR_JLIST,
defaults.
PANEL NOTIFY PROC,
0);
name proc.
addres s_item
= panel_create_item(PANEL TEXT,
ATTR_LIST,
defaults.
PANEL_SHOW_ITEM,
TRUE,
S
PANEL VALUE FONT,
0);
big_font.
j
The special attribute ATTR_LIST takes as its value an attribute list. In the
above example, first an attribute list called defaults is created. Then, by
mentioning defaults first in the attribute lists for subsequent item creation
calls, each item takes on those default attributes. Subsequent references to an
attribute override the setting in defaults since the last value mentioned for an
attribute is the one which takes effect.
18.3. Maximum Attribute The maximum length of attribute-value lists supported by the SunView packages
List Size (see ATTR_STANDARD_SIZE in <sunwindow/attr . h>) is 250. If the
number of attributes in a list you pass to SunView exceeds this size, the attribute
package prints
on standard output and exits with exit status 1.
V microsystems
Revision A, of May 9,1988
SunView Interface Summary
SunView Interface Summary... 315
Alert Tables. 316
Attributes. 3 16
Functions. 318
Canvas Tables. 319
Attributes. 319
Functions and Macros. 320
Cursor Tables. 321
Attributes. 321
Functions. 323
Data Types. 324
Icon Tables. 328
Attributes. 328
Functions and Macros. 329
Input Event Tables. 339
Event Codes. 339
Event Descriptors. 333
Input-Related Window Attributes. 334
Menu Tables. 335
Attributes. 335
Item Attributes. 339
Functions. 341
Notifier Functions Table. 343
Notifier Functions Table. 343
Panel Tables. 346
Attributes. 346
Generic Panel Item Attributes. ' . 347
Choice and Toggle Item Attributes. 349
Slider Item Attributes... 351
Text Item Attributes. 352
Functions and Macros. 353
Pixwin Tables . 356
Pixwin Drawing Functions and Macros Table. 356
Pixwin Color Manipulation Functions Table. 360
Attributes. 362
Functions and Macros. 365
Text Subwindow Tables. 366
Attributes. 366
Textsw_action Attributes. 370
Textsw_status Values. 371
Functions... 372
TTY Subwindow Tables. 376
Attributes. 376
Functions. 376
Special Escape Sequences. 377
Window Tables. 379
Attributes. 379
Frame Attributes. 382
Functions and Macros. 384
Command Line Frame Arguments. 386
SunView Interface Summary
This chapter contains tables summarizing the data types, functions and attributes
which comprise the SunView programmatic interface. 101
The tables correspond to the chapters in this book, but are in alphabetical order:
Alerts, Canvases, Cursors, Data Types, Icons, Input (including events and input-
related window atttributes), Menus, the Notifier, Panels, Pixwins, Scrollbars,
Text Subwindows, TTY Subwindows and Windows (including frames and frame
command line arguments).
Note that the order of the chapters is different than the order of the tables. The
chapter on windows (including frames) comes first, followed by canvases, input,
pixwins, text subwindows, panels, alerts, tty subwindows, menus, cursors, icons,
scrollbars, the Selection Service, and the Notifier.
Within each topic, the attribute tables come first, then the functions and macros,
then miscellaneous tables.
To help distinguish where one table ends and another begins, the start of each
table is marked with a horizontal grey bar.
101 This chapter does not include a table for the Selection Service functions; see the SunView System
Programmer’s Guide for a complete discussion of the Selection Service interface.
\r microsystems
315
Revision A, of May 9,1988
316 SunView 1 Programmer’s Guide
Table 19-1 Alert Attributes
Attribute
Type
Description
ALERT_BUTTON
char *, int
A string to be displayed in a button and a value to associate with it The
value specified with the string will be returned when the button is
selected. The value may be any integer, but should not be a value
predefined by the alerts package; that is, not ALERT_YES, ALERT_NO,
ALERT_FAILED, or ALERT_DEFAULT_TRIGGERED).
See the values given in the Alert Functions table.
ALERT_BOTTON_FONT
Pixfont *
Font used for buttons. Default is the font specified for menus, which is
Menu!Font in defaultsedit or screen. b. 14 if no default is specified.
ALERT_BUTTON_NO
char *
A string that is associated with the accelerated
NO (cancel, don’t do it) button which is triggered via a
keyboard accelerator. The value returned if this button is selected
(or the accelerator is triggered) will be ALERT_NO. Only one instance
of this attribute is allowed.
ALERT_BUTTON_YES
char *
A string to associate with the accelerated
YES (ie. confirm, continue, do it) button which is also triggered via a
keyboard accelerator. The value returned when this button is selected
(or the accelerator is triggered) will be ALERT_YES. Only one instance
of this attribute is allowed.
ALERT_MESSAGE_FONT
Pixfont *
Font used for message strings.
The default is the same as Client Frame (if specified) otherwise it is the
same as SunView/Font.
ALERT_MESSAGE_STRINGS
list char*
Strings to be displayed in the message
area of the alert panel. The default is to be determined.
ALERT_MES SAGE_STRINGS_ARRAY_P TR
array char*
Same as ALERT_MESSAGE_STRINGS
except the client need not know the actual strings being passed, just
that the value is pointer to first of null terminated array of strings.
The alerts package will cast the value into a type char **.
ALERT_N 0_BEEPING
int
Allows the client to specify that no beeping should
take place reguardless of defaults database setting. The default for this
option is FALSE; that is, beep however many times database specifies.
Revision A, of May 9,1988
Chapter 19 — SunView Interface Summary (Alert Attributes) 317
Table 19-1
Alert Attributes — Continued
Attribute
Type
Description
ALERT
_OPTIONAL
boolean
Specifies whether an optional alert will be enabled
or disabled. You make an alert a
courtesy alert by specifing the ALERT_OPT IONAL
attribute in the attribute list passed to
alert_prompt ().
ALERT_
POSITION
int
Specifies the position of the alert.
Default is ALERT_CLIENT_CENTERED unless client_frame = NULL
NULL causes the alert to default to ALERT_SCREEN_CENTERED
regardless of this setting.
Possible values that may be passed are: ALERT_SCREEN CENTERED,
ALERT_CLIENT_CENTERED, and ALERT_CLIENT_OFFSET.
Use WIN_X and WIN_Y for the offset attributes. This position describes
where the “center” of an alert should be.
ALERT_
TRIGGER
int
This special attribute allows the client to
specify a SunView event which should cause the alert to return. The
default is not to return unless an actual button has been selected
or the other YES/NO accelerators are seen. When this event is triggered,
the value returned will be ALERT__TRIGGERED.
microsystems
Revision A, of May 9, 1988
318 Sun View 1 Programmer’s Guide
Table 19-2 Alert Functions
Definition Description
int
alert_prompt(client frame, event, attributes)
Frame client__f rame;
Event *event;
<attribute-list> attributes;
Displays alert and doesn’t return until the user pushes a
button, or its trigger or the default has been seen. A value
of ALERT_FA I LED is returned if alert_prompt ()
failed for any reason, otherwise equivalent to ordinal value
of button which caused return (ie. button actually selected,
or default button if default action triggered return). The
client_frame may be NULL (see ALERT_P0SITI ON for
consequences). The event will be completely filled in at
the time the alert_prompt () returns.
The possible status values that may be returned from this
function are: the (int) value passed with every
ALERT_BUTTON attribute; ALERT_YES, if a confirm but¬
ton or trigger was pushed; ALERT_NO, if a cancel button or
trigger was pushed; ALERT_FAILED, if the alert failed to
pop up; and ALERT_TRIGGERED, if a keyboard accelera¬
tor was used.
*
microsystems
Revision A, of May 9, 1988
Chapter 19 — SunView Interface Summary (Canvas Attributes) 319
Table 19-3 Canvas Attributes
Attribute
Type
. . '■. . . . . . . . ... . . .......... |
Description
CANVAS_AUT 0_CLEAR
boolean
If TRUE, repaint area of canvas pixwin is cleared before,
repaint proc is called. Default: TRUE unless the canvas is retained.
CANVAS_AUTO_EXPAND
boolean
If TRUE, canvas width and height are never allowed to be
less than the edges of the canvas pixwin. Default: TRUE.
CANVAS__AUTO_SHRI NK
boolean
If TRUE, canvas width and height are never allowed to be
greater than the edges of the canvas pixwin. Default: TRUE.
CANVAS_FAST_MONO
boolean
If TRUE, tells canvases and graphics sub windows to use
the monochrome overlay plane of the Sun-3/110 display. Default: FALSE.
CANVAS_FIXED_IMAGE
boolean
If TRUE, canvas package assumes that client is drawing a fixed-size image
whose rendering does not depend on the size of the canvas. Default: TRUE.
CANVAS_HEIGHT
int
Height of object being drawn. Default: height of usable window, which is
WIN_HEIGHT - (SCROLL_THICKNESS of WIN_HORIZONTAL_SCROLLBAR) -
CANVAS_MARGIN*2.
CANVAS_MARGIN
int
Margin to leave around the canvas pixwin from inside of window. Default: 0.
CANVAS_PIXWIN
Pixwin *
Pixwin for drawing. Get only.
CANVAS_REPAINT__PROC
(procedure)
Called when repaint needed, even if retained. Default: NULL. Form:
repaint_proc(canvas, pixwin, repaint_area)
Canvas canvas;
Pixwin *pixwin;
Rectlist *repaint area;
CANVAS_RESIZE_PROC
(procedure)
Called when canvas width or height changes. Default: NULL. Form:
resize_proc(canvas, width, height)
Canvas canvas;
int width;
int height;
CANVAS_RETAINED
boolean
If TRUE, image is backed up for repaint. Default: TRUE.
CANVAS_WIDTH
int
Width of object being drawn. Default: width of usable window, which is
WIN_WIDTH - (SCROLLJTHICKNESS of WIN_VERTICAL_SCROLLBAR) -
CANVAS_MARG I N*2.
microsystems
Revision A, of May 9, 1988
320 SunView 1 Programmer’s Guide
Table 19-4 Canvas Functions and Macros
microsystems
Revision A, of May 9, 1988
Chapter 19 — SunView Interface Summary ( Cursor Attributes) 321
Table 19-5 Cursor Attributes
Attribute
Value Type
Description
C0RS0R_CR0SSHAIRJ30RDER_GRAVITY
boolean
Crosshairs stick to borders. Default: FALSE.
CURSOR_CROSSHAIR_COLOR
int
Color for crosshairs. Default: 1. (Note: the color displayed
depends on the settings in your colormap segment).
CURSOR_CROSSHAIR_GAP
int
Half-length of space to leave untouched from intersection of
crosshairs. Value of CURSOR_TO_EDGE extends crosshairs to
edge of cursor rect Default: 0.
CURSOR_CROSSHAIR_LENGTH
int
Half-length of crosshairs. Default: CURSOR TO EDGE.
CURSOR_CROSSHAI R__OP
int
Raster op for drawing crosshairs. Default: PIX__SRC.
CURSOR_CROSSHAIRJTHICKNESS
int
Thickness of crosshairs. Maximum value is
CURSOR_MAX_HAIR_THICKNESS (5). Default: 1.
CURSOR_FULLS CREEN
boolean
Clip crosshairs to edge of screen not window. Default: FALSE.
CURSOR_HORIZ_HAIR_BORDER_GRAVI TY
boolean
Horizontal crosshair sticks to borders. Default: FALSE.
CURSOR_HORIZ_HAIR_COLOR
int
See CURSOR_HORI Z__HAIR__COLOR
CURS OR_HOR I Z_HA I R__GAP
int
See CURSOR_CROSSHAIR_GAP.
CURSOR_HORIZ_HAIR_LENGTH
int
See CURSOR_CROSSHAIR__LENGTH.
CURSOR_HORI Z_HAIR_OP
int
Raster op for drawing horizontal crosshair. Default: PIX SRC.
CURSOR_HORIZ_HAIR_THICKNESS
int
See CURSOR_CROSSHAIR__THICKNESS.
CURS OR_IMAGE
Pixrect *
Cursor’s image. Default: 16x16x1 blank pixrect.
CURSOR_OP
int
Raster op for drawing cursor image.
Default: PIX_SRC | PIX_DST.
CURSOR_SHOW_CROSSHAIRS
boolean
Show or don’t show crosshairs. Default: FALSE.
CURSOR_SHOW_CURSOR
boolean
Show or don't show cursor image. Default: TRUE.
CURSOR_SHOW_HORIZ_HAIR
boolean
Show or don’t show horizontal crosshair. Default: FALSE.
CURSOR_SHOW_VERT_HAIR
boolean
Show or don’t show vertical crosshair. Default: FALSE.
Xr microsystems
Revision A, of May 9, 1988
322 SunView 1 Programmer’s Guide
Table 19-5 Cursor Attributes—Continued
Attribute Value Type _ Description _
Vertical crosshair sticks to borders. Default: FALSE.
CURSOR VERT HAIR BORDER GRAVITY
boolean
CURSOR_VERT_HAIR_COLOR
int
CURSOR_VERT_HAIR_GAP
int
CURSOR_VERT_HAI R__LENGTH
int
CURSOR_VERT_HAI R_OP
int
CURSOR_VERT_HAI R_THICKNESS
int
CURS OR_XHOT
int
CURSOR YHOT
int
See CURSOR_CROSSHAIR_COLOR
See CURSOR_CROSSHAIR_GAP.
See CURSOR_CROSSHAIR_LENGTH.
Raster op for drawing vertical crosshair. Default: PIX_SRC.
See CURSOR_CROSSHAIR_THICKNESS.
Hot spot x coordinate. Default: 0.
Hot spot y coordinate. Default: 0.
Asun
\T microsystems
Revision A, of May 9, 1988
Chapter 19 — SunView Interface Summary (Cursor Functions) 323
Table 19-6 Cursor Functions
Definition
Description
Cursor
cursor__copy (src cursor)
Cursor src_cursor;
Creates and returns a copy of src cursor.
Cursor
cursor_create(attributes)
<attribute-list> a11 ribute s;
Creates and returns the opaque handle to a cursor.
void
cursor_destroy(cursor)
Cursor cursor;
Destroys cursor.
caddr_t
cursor_get(cursor, attribute)
Cursor cursor;
Cursor__attribute attribute;
Retrieves the value for an attribute of cursor.
void
cursor__set (cursor, attributes)
Cursor cursor;
<attribute-list> attributes;
Sets the value for one or more attributes of cursor.
attributes is a null-terminated attribute list.
microsystems
Revision A, of May 9, 1988
324 SunView 1 Programmer’s Guide
Table 19-7
Data Types
Data Type
Description
Canvas
Pointer to an opaque structure which describes a canvas.
Cursor
Pointer to an opaque structure which describes a cursor.
Destroy_status
Enumeration: DESTROY_PROCESS_DEATH,
DESTROY_CHECKING, or DESTROY_CLEANUP.
Event
The structure which describes an input event:
typedef struct inputevent {
short ie_code;
short ie__flags;
short ie_shiftmask;
short ie_locx;
short ie__locy;
struct timeval ie_time;
} Event;
Frame
Pointer to an opaque structure which describes a frame.
Icon
Pointer to an opaque structure which describes a icon.
Inputmask
Mask specifying which input events a window will receive.
Menu
Pointer to an opaque structure which describes a menu.
Menu_at.tr ibute
One of the menu attributes (MENU_*).
Menu_generate
Enumerated type of the operation parameter passed to generate procs:
MENU CREATE, MENU DESTROY, MENU_NOTIFY_CREATE or MENU_NOTIFY_DESTROY.
Menu item
Pointer to an opaque structure which describes a menu item.
Notify_arg
Opaque client optional argument.
Notify_destroy
Enumeration: NOT I FY_SAFE, NOT I FY__I MMEDI ATE.
(See also Notify_event_type).
Notify_event
Opaque client event.
XT microsystems
Revision A, of May 9, 1988
Chapter 19 — SunView Interface Summary (Data Types) 325
Table 19-7
Data Types — Continued
Data Type
Description
Notify_error
Enumeration of errors for notifier functions:
NOTIFY_OK, NOTIFY_UNKNOWN_CLIENT, NOTIFY_NO_CONDITION,
NOTIFY_BAD_ITIMER, NOTIFY_BAD_SIGNAL, NOTIFY_NOT_STARTED,
NOTIFY_DESTROY_VETOED, NOTIFY_INTERNAL_ERROR, NOTIFY_SRCH,
NOTIFY_BADF, NOTIFY_NOMEM, NOTIFY_INVAL, or NOTIFY_FUNC_LIMIT.
Notify_event type
Enumeration: NOTIFY_SAFE, NOTIFY_IMMEDIATE.
Notify func
Notifier function.
Notify_signal_mode
Enumeration: NOTIFY_SYNC, NOTIFY_ASYNC.
Notify_value
Enumeration of possible return values for client notify procs:
NOTIFY_DONE, NOTIFY_IGNORED, or NOTIFY_UNEXPECTED.
Panel
Pointer to an opaque structure which describes a panel.
Panel_attribute
One of the panel attributes (PANEL *).
Panel_item
Pointer to an opaque structure which describes a panel item.
Panel_setting
Enumerated type returned by panel_text_not ify ();
also type of repaint argument to panel_paint ().
See the Panels chapter and <suntool/panel. h>.
Pixfont
The structure representing a font (for definition see the Pixrect Reference Manual).
Pixrect
The basic object of pixel manipulation in the SunView window system. Pixrects
include both a rectangular array of pixels and the means of accessing operations
for manipulating those pixels (for definition see the Pixrect Reference Manual).
Pixwin
The basic imaging element of the SunView window system. While, for
historical reasons, its fields are public, clients should treat it as an opaque handle.
Rect
The structure describing a rectangle:
typedef struct rect {
short r_left;
short r__top;
short r_width;
short r_height;
} Rect;
v microsystems
Revision A, of May 9, 1988
326 SunView 1 Programmer’s Guide
Table 19-7
Data Types — Continued
Data Type
Description
Rectlist
A list of rectangles:
typedef struct rectlist {
short rl_x, rl_y;
Rectnode *rl_head;
Rectnode *rl_tail;
Rect rl_bound;
} Rectlist;
typedef struct rectnode {
Rectnode *rn_next;
Rect rn_rect;
} Rectnode;
Scroll_motion
Enumerated type representing possible scrolling motions:
SCROLL_ABSOLUTE, SCROLL_FORWARD, SCROLL_MAX_TO_POINT,
SCROLL_PAGE_FORWARD, SCROLL_LINE_FORWARD,
SCROLL_BACKWARD, SCROLL_POINT_TO_MAX,
SCROLL__P AGE_BACKWARD, or SCROLL_L I NE_BACKWARD.
Scrollbar
The opaque handle for a scrollbar.
Scrollbar_attribute
One of the scrollbar attributes (SCROLL_*).
Scrollbar_setting
The value of an enumerated type scrollbar attribute.
Textsw
Pointer to an opaque structure which describes a text subwindow.
Text sw_index
An index for a character within a text subwindow.
Textsw enum
Enumerated type for various text subwindow attribute values:
TEXTSW_ALWAYS, TEXTSW_NEVER, TEXTSW_ONLY,
TEXTSW_IF_AUTO__SCROLL, TEXTSW_CLIP,
TEXTSW_WRAP_AT_CHAR, TEXTSW_WRAP_AT_WORD.
Textsw_status
Enumeration describing the status of text subwindow operations:
TEXTSW ST AT U S_OKA Y, TEXT SW_ST ATU S_BAD_ATTR,
TEXTSW ST AT U S_BAD_ATTR_VALUE, TEXT SW_ST ATU S_CANNOT_ALLOCATE,
TEXTSW STATUS CANNOT_OPEN_INPUT, or TEXTSW_STATUS_OTHER_ERROR,
Tty
Pointer to an opaque structure which describes a tty sub window.
Window
Pointer to an opaque structure which describes a window.
Revision A, of May 9, 1988
Chapter 19 — SunView Interface Summary (Data Types) 327
Table 19-7
Data Types — Continued
Data Type
Description
Window_attribute
One of the window attributes (WIN *).
Window type
Type of window, retrieved via the WIN TYPE attribute. One of:
FRAME_TYPE, PANEL_TYPE, CANVASJTYPE, TEXTSW TYPE, or TTY TYPE.
#sun Revision A, of May 9, 1988
V microsystems
328 SunView 1 Programmer’s Guide
Table 19-8 Icon Attributes
Attribute
Type
Description
ICON_FONT
Pixfont *
Font for icon’s label.
ICON_HEIGHT
int
Icon’s height in pixels. Default: 64.
ICON_IMAGE
Pixrect*
Memory pixrect for icon’s image.
I CON__I MAGE_RE CT
Rect *
Rect for icon’s image. Default: origin (0,0), width 64, height 64.
ICON_LABEL
char *
Icon’s label.
ICON_LABEL_RECT
Rect *
Rect for icon’s label. Default: origin (0, 0), width 0, height 0.
ICON_WIDTH
int
Icon’s width in pixels. Default: 64.
xr microsystems
Revision A, of May 9, 1988
Chapter 19 — SunView Interface Summary (Icon Functions and Macros) 329
Table 19-9 Icon Functions and Macros
Definition
Description
Icon
icon_create(attributes)
Creates and returns the opaque handle to an icon.
<attribute-list> att ribut e s;
int
icon_destroy (icon) Destroys icon.
Icon icon;
caddr_t
icon_get (icon, attribute) Retrieves the value for an attribute of icon.
Icon icon;
Icon_attribute attribute;
int
icon_set (icon, attributes) Sets the value for one or more attributes of icon.
Icon icon; attributes is a null-terminated attribute list
<attribute-list> attributes;
extern static struct mpr_data Macro that creates a static memory pixrect
DEFINE_ICON_FROM_IMAGE (name, image) icon from image; the latter typically is gen-
static short icon_image [] ; erated by including a file created by iconedit.
Note: you must pass the address of icon to the
_icon routines, since the Icon object is a pointer.
microsystems
Revision A, of May 9,1988
330 SunView 1 Programmer’s Guide
Table 19-10 Event Codes
Event Code
Description
Value (for debugging)
ASCII_FIRST
Marks beginning of ASCII range
0
ASCII LAST
Marks end of ASCII range
127
META FIRST
Marks beginning of META range
128
META_LAST
Marks end of META range
255
ACTION ERASE CHAR BACKWARD
Erase char to the left of caret
31744
ACTION ERASE CHAR FORWARD
Erase char to the right of caret
31745
ACTION ERASE WORD BACKWARD
Erase word to the left of caret
31746
ACTION ERASE WORD FORWARD
Erase word to the right of caret
31747
ACTION ERASE LINE BACKWARD
Erase to the beginning of the line
31748
ACTION_ERASE_LINE_END
Erase to the end of the line
31749
ACTION GO CHAR BACKWARD
Move the caret one character to the left
31752
ACTION GO CHAR FORWARD
Move the caret one character to the right
31753
ACTION GO WORD BACKWARD
Move the caret one word to the left
31754
ACTION GO WORD END
Move the caret to the end of the word
31756
ACTION_GO_WORD_FORWARD
Move the caret one word to the right
31755
ACTION_GO_LINE_BACKWARD
Move the caret to the start of the line
31757
ACTION_GO_LINE_END
Move the caret to the end of the line
31759
ACTION_GO_LINE_FORWARD
Move the caret to the start of the next line
31758
ACTION_GO_COLUMN_BACKWARD
Move the caret up one line,
maintaining column position
31761
ACTION_GO_COLUMN_FORWARD
Move the caret down one line,
maintaining column position
31762
ACTION_GO_DOCUMENT_START
Move the caret to the beginning of the text
31763
ACTION_GO_DOCUMENT_END
Move the caret to the end of the text
31764
ACTION_STOP
Stop the operation
31767
ACTION_AGAIN
Repeat previous operation
31768
ACTION_PROPS
Show property sheet window
31769
ACTION_UND0
Undo previous operation
31770
ACTION_FRONT
Bring window to the front of the desktop
31772
ACTION_BACK
Put the window at the back of the desktop
31773
ACTION_OPEN
Open a window from its icon form or close
if already open)
31775
ACTION_CLOSE
Close a window to an icon
31776
ACTION_COPY
Copy the selection to the clipboard
31774
ACTION_PASTE
Copy clipboard contents to the insertion point
31777
ACTION_CUT
Delete the selection, put on clipboard
31781
ACTION_COPY_THEN_PASTE
Copies then pastes text
31784
ACTION_FIND_FORWARD
Find the text selection to the right of the caret
31779
ACTION_FIND_BACKWARD
Find the text selection to the left of the caret
31778
ACTION_FIND_AND_REPLACE
Show find and replace window
31780
ACTION SELECT FIELD FORWARD
Select the next delimited field
31783
#sun
microsystems
Revision A, of May 9, 1988
Chapter 19 — SunView Interface Summary (Input Event Codes) 331
Table 19-10 Event Codes — Continued
Event Code
Description
Value (for debugging)
ACTION_SELECT_FIELD_BACKWARD
Select the previous delimited field
31782
ACTION_MATCH_DELIMITER
Selects text up to a matching delimiter
31894
ACTI ON__QUOTE
Causes next event in the input stream to
pass untranslated by the keymapping system
31898
ACT10N_EMP TY
Causes the sub window to be emptied
31899
ACTION_STORE
Stores the specified selection as a new file
31785
ACTIONJLOAD
Loads the specified selection as a new file
31786
ACTI ON_GET_F ILENAME
Gets the selected filename
31788
ACTION_SET_DIRECTORY
Sets the directory to the selection
31788
ACTION_INCLUDE_FILE
Selects the current line (in pending-delete mode)
and attempts to insert the file described by that selection
31891
ACTION_CAPS_LOCK
Toggle caps lock state
31895
PANEL_EVENT_CANCEL
The panel or panel item is no longer “current”
32000
PANEL_EVENT_MOVE_IN
The panel or panel item was entered
with no mouse buttons down
32001
PANEL_EVENT_DRAG_IN
The panel or panel item was entered with one or more
mouse buttons down
32002
SCROLL_REQUEST
Scrolling has been requested
32256
SCROLL_ENTER
Locator (mouse) has moved into the scrollbar
32257
SCROLL_EXI T
Locator (mouse) has moved out of the scrollbar
32258
LOC_MOVE
Locator (mouse) has moved
32512
LOC_STILL
Locator (mouse) has been still for 1/5 second
32513
LOC_WINENTER
Locator (mouse) has entered window
32514
LOC_WINEXIT
Locator (mouse) has exited window
32515
LOC_DRAG
Locator (mouse) has moved while a button was down
32516
LOC_RGNENTER
Locator (mouse) has entered a region of the window
32519
LOC_RGNEXIT
Locator (mouse) has exited a region of the window
32520
LOC_TRAJECTORY
Inhibits the collapse of mouse motions; clients receive
LOC_TRA JECTORY events for every locator motion
the window system detects.
32523
WIN_REPAINT
Some portion of window requires repainting
32517
WIN_RESIZE
Window has been resized
32518
WIN_STOP
User has pressed the stop key
32522
KBD_REQUEST
Window is about to become the focus of keyboard input
32526
KBD_USE
Window is now the focus of keyboard input
32524
KBD_DONE
Window is no longer the focus of keyboard input
32525
SHIFT_LEFT
Left shift key changed state
32530
SHIFT_RIGHT
Right shift key changed state
32531
SHIFT_CTRL
Control key changed state
32532
SHIFT_META
Meta key changed state
32534
SHIFT JLOCK
Shift lock key changed state
32529
Revision A, of May 9, 1988
332 SunView 1 Programmer’s Guide
Table 19-10 Event Codes — Continued
Event Code
Description
Value (for debugging)
SHIFT_CAPSLOCK
Caps lock key changed state
32528
BUT(i)
Locator (mouse) buttons 1-10
BUT(l) is 32544
MS_LEFT
Left mouse button
32544
MS_MIDDLE
Middle mouse button
32545
MS_RIGHT
Right mouse button
32546
KEY_LEFT(i)
Left function keys 1-15
KEY_LEFT (1) is 32554
KEY_RIGHT(i)
Right function keys 1-15
KEY_RIGHT (1) is 32570
KEYJTOP(i)
Top function keys 1-15
KEYJTOP (1) is 32586
Revision A, of May 9, 1988
Chapter 19 — SunView Interface Summary (Input Event Descriptors) 333
Table 19-11 Event Descriptors
Event Descriptor
Explanation
WIN_N0_EVENTS
Clears input mask — no events will be accepted. Note: the
effect is the same whether used with a consume or an
ignore attribute. A new window has a cleared input mask.
WIN_ASCII__E VENTS
All ASCH events. ASCII events that occur while the META
key is depressed are reported with codes in the META range.
In addition, cursor control keys and function keys are
reported as ANSI escape sequences: a sequence of events
whose codes are ASCII characters, beginning with <ESC>.
WI N_IN__TRAN SI T_E VENT S
Enables immediate LOC_MOVE, LOC WINENTER, and
LOC_WINEXIT events. Pick mask only. Off by default.
WIN__LEFT_KEYS
The left function keys, KEY_LEFT(1) — KEY_LEFT(15).
WIN_MOUSE_BUTTONS
Shorthand for MS_RIGHT, MS_MIDDLE and MS LEFT.
Also sets or resets WIN_UP EVENTS.
WI N_R I GHT_KE Y S
The right function keys, KEY_RIGHT(1) — KEY_RIGHT(15).
WI N__T OP_KE Y S
The top function keys, KEY_TOP(l) — KEY_TOP(15).
WIN_UP_ASCI I_EVENTS
Causes the matching up transitions to normal
ASCH events to be reported — if you see an V
go down, you’ll eventually see the matching ’a’ up.
WIN_UP_EVENTS
Causes up transitions to be reported for button
and function key events being consumed.
microsystems
Revision A, of May 9, 1988
334 SunView 1 Programmer’s Guide
Table 19-12 Input-Related Window Attributes
Attribute
Value Type
Description
WIN_INPUT_DESIGNEE
int
Window which gets events this window doesn’t consume.
(Note that the value must be the designee’s WIN_DEVICE_NUMBER).
WI N_GRAB__ALL__INPUT
boolean
Window will get all events regardless of location.
WIN_KBD_FOCUS
boolean
Whether or not the window has the keyboard focus.
WIN_KBD_INPUT_MASK
Inputmask *
Window’s keyboard inputmask.
WIN_PICK_INPUT_MASK
Inputmask *
Window’s pick inputmask.
WIN_CONSUME_KBD_EVENT
short
Window will receive this event.
WIN_IGNORE_KBD_EVENT
short
Window will not receive this event.
WIN_CONSUME_KBD_EVENTS
short list
Null terminated list of events window will receive.
WIN_IGNORE_KBD_EVENTS
short list
Null terminated list of events window will not receive.
WIN_CONSUME_PICK_EVENT
short
Window will receive this pick event.
WIN_IGNORE_PICK_EVENT
short
Window will not receive this pick event.
WIN_CONSUME_PICK_EVENTS
short list
Null terminated list of pick events window will receive.
WIN_IGNORE_PICK_EVENTS
short list
Null terminated list of pick events window will not receive.
microsystems
Revision A, of May 9, 1988
Chapter 19 — SunView Interface Summary {Menu Attributes) 335
Table 19-13 Menu Attributes
Attribute
Value Type
Description
MENU_ACTION_IMAGE
Pixrect *, action proc
Create image menu item with action proc. Set only.
MENU_ACTION_ITEM
char *, action proc
Create string menu item with action proc. Set only.
MENU_APPEND_ITEM
Menu_item
Append item to end of menu. Set only.
MENUJ30XED
boolean
If TRUE, a single-pixel box will be drawn around
every menu item.
MENU_CENTER
boolean
If TRUE, all string items in the menu will be centered. Default: FALSE
MENU_CLIENT_DATA
caddr_t
For client’s use.
MENU_COLUMN_MAJOR
boolean
If TRUE, string items in the menu will be sorted in column-major
order (like ls(l)) instead of row-major order. Default: FALSE
MENU_CLIENT_DATA
caddr_t
For client’s use.
MENU_DESCEND__FIRST
(no value)
For menu_f ind (). If given, search will
be depth first, else search will be "deferred".
MENU_DEFAULT
int
Default menu item as a position.
MENU_DEFAULT__I TEM
Menu_item
Default menu item as opaque handle.
MENU_DEFAULT_SELECTION
enum
Either MENU_SELECTED or MENU_DEFAULT.
MENU_FIRST_EVENT
Event *
The event which was initially passed into
menu_show (). Get only.
(Note that the event’s contents can be modified.)
MENU_FONT
Pixfont *
Menu’s font.
MEN U_GEN_PROC
(procedure)
Client’s function called to generate the menu.
Menu gen_proc(m, op)
Menu m;
Menu_generate op;
MENU_GEN_P ULLRI GHT_I MAGE
Pixrect *, gen proc
Create image menu item with
generate proc for pullright. Set only.
MENU_GEN_PULLRIGHT_I TEM
char *, gen proc
Create string menu item with
generate proc for pullright. Set only.
MENU_IMAGE_ITEM
Pixrect *, value
Create image menu item with value. Set only.
microsystems
Revision A, of May 9, 1988
336 SunView 1 Programmer’s Guide
Table 19-13 Menu Attributes— Continued
Attribute
Value Type
Description
MENU_IMAGES
list of Pixrect *
Create multiple image menu items. Set only.
MENU_INITIAL_SELECTION
enum
Either MENU__SELECTED or MENU_DEFAULT.
MENU INITIAL SELECTION EXPANDED boolean
If TRUE, when the menu pops up, it
automatically expands to select the initial selection.
MENU INITIAL SELECTION_SELECTED boolean
If TRUE, menu comes up with its initial
selection highlighted. If FALSE, menu comes
up with the cursor "standing off' to the left
MENU_INSERT
int, Menu_item
Insert new item after nth item. Set only.
MENU INSERT ITEM
Menu_item, Menu_item The item given as the second value is inserted
after the one given as the first value. Set only.
MENU ITEM
avlist
Create a menu item inline — avlist same as for
menu_create_item (). Set only.
MENU_JUMP_AFTER_NO_SELECTION
boolean
If TRUE, cursor jumps back to its
original position after no selection made.
MENU_JUMP_AFTER_SELECTION
boolean
If TRUE, cursor jumps back to its
original position after selection made.
MENU_LAST_EVENT
Event*
The last event read by the menu. Get only.
Note that the event’s contents can be modified.
MENU_LEFT_MARGIN
int
For each string item, margin in addition to
MENU MARGIN on left between menu’s
border and text. Default: 16.
MENU_MARGIN
int
Margin in pixels around menu items. Default: 1.
MENU_NCOLS
int
Number of columns in menu.
MENU_NITEMS
int
Get only; returns the # of items in the menu.
MENU_NROWS
int
Number of rows in menu.
MENU_NOTIFY_PROC
(procedure)
Client’s function called when the user selects
a menu item.
caddr_t notify_proc(m, mi)
Menu m;
Menu item mi;
Revision A, of May 9, 1988
Chapter 19 — SunView Interface Summary (Menu Attributes) 337
Table 19-13 Menu Attributes — Continued
Attribute
Value Type
Description
MENU_NTH_ITEM
int
starting from 1.
Get only; returns nth menu item, n is counted
MENU__PARENT
Menu_item
The menu item for which the menu is a pullright. Get only.
MENU_P ULLRIGHT_DELTA
int
Number of pixels the user must move the cursor
to the right to cause a pullright menu to pop up.
Default: 9999.
MENUJP ULLRI GHT__I MAGE
Pixrect *, Menu
Create image menu item with pullright. Set only.
MENU_P ULLRI GHT_I TEM
char *, Menu
Create string menu item with pullright Set only.
MENU_REMOVE
int
Remove the nth item. Set only.
MENU_REMOVE_ITEM
Menu_item
Remove the specified item. Set only.
MENU_REP LACE
int, Menu_item
Replace nth item with specified item. Set only.
MENU_REPLACE__I TEM
Menu_item, Menu_item The item given as first value is replaced
with the one given as the second value
in the menu (the old item is not replaced
in any other menus it may appear in). Set only.
MENU_R I GHT_MARGI N
int
For each string item, margin in addition to
MENU_MARGIN on right
between menu’s border and text.
MENU_SELECTED
int
Last selected item, as a position in menu.
MENU_SELECTED_ITEM
Menujtem
Last selected item, as the item’s handle.
MENU_SHADOW
Pixrect *
Pattern for the shadow to be painted behind
the menu. If 0, no shadow is painted.
Predefined shadow pixrects you can use:
menu_gray25 _pr, menu__gray50_pr,
and menu_gray 7 5_pr.
MENU_STAY__UP
boolean
If TRUE the first click of the Menu button puts up the menu, the
second takes it down; in between, the menu stays up. Default: FALSE
MENU_STRINGS
list of char *
Create multiple string menu items. Set only.
MENU_STRING_ITEM
char *, value
Create string menu item with value. Set only.
Revision A, of May 9,1988
338 SunView 1 Programmer’s Guide
Table 19-13 Menu Attributes — Continued
Attribute
Value Type
Description
MENU_TITLE_
IMAGE
Pixrect*
Create image title item. Set only.
MENU_TITLE_
ITEM
char *
Create string title item. Set only.
MENU_TYPE
enum
Get only; returns MENU_MENU.
MENU_VALID_
_RESULT
boolean
Tells whether a zero return value represents a legitimate value.
Revision A, of May 9, 1988
Chapter 19 — SunView Interface Summary (Menu Item Attributes) 339
Table 19-14 Menu Item Attributes
Attribute
Value Type
Description
MENU_ACTION_IMAGEt
Pixrect *, action proc
Modifies appropriate fields in item. Set only.
MENO_ACTION_ITEMf
char *, action proc
Modifies appropriate fields in item. Set only.
MENU_ACTION_PROC
(procedure)
Client’s function called after item has been selected:
caddr_t action_proc(menu, menu_item)
Menu menu
Menu_item menu_itern
MENO_APPEND_ITEMf
Menujtem
Append item to end of menu. Set only.
MENU_BOXEDf
boolean
If TRUE, a single-pixel box will be drawn around the item.
MENU_CENTERf
boolean
If TRUE, the menu item will be centered on its row in the menu.
Only meaningful for menu strings.
MENU_CLIENT_DATAf
caddr_t
For use by the client.
MENU_FEEDBACK
boolean
If FALSE, item is never inverted and is not selectable.
MENU_FONTf
Pixfont *
Item’s font.
MENO_GEN_PROCf
(procedure)
Client’s procedure called to generate the item.
MENU_GEN_PROC_IMAGE
Pixrect *, (procedure)
Modifies appropriate fields in item. Set only.
MENU_GEN_PROC_ITEM
char *, (procedure)
Modifies appropriate fields in item. Set only.
MENU_GEN_PULLRIGHT
generate proc
Generate proc for the item’s pullright.
MENU_GEN_PULLRIGHT_IMAGEf
Pixrect *, (procedure)
Modifies appropriate fields in item. Set only.
MENU_GEN_PULLRIGHT_ITEMf
char *, gen proc
Modifies appropriate fields in item. Set only.
MENU_IMAGE
Pixrect *
Item’s image.
MENU_IMAGE_ITEMf
char *, action proc
Modifies appropriate fields in item. Set only.
MENU_INACTIVE
boolean
If TRUE, item is grayed out and not selectable.
t Many of the attributes in this table appeared in the previous table. Menus and menu items have many attributes in common. Attributes marked with
“f” are also valid for menus, although the effect of the attribute may differ.
microsystems
Revision A, of May 9, 1988
340 SunView 1 Programmer’s Guide
Table 19-14 Menu Item Attributes — Continued
Attribute
Value Type
Description
MENU_INVERT
boolean
If TRUE, item’s display is inverted.
MENU_LEFT_MARGINf
int
Margin in addition of MENU_MARGIN on left between
menu’s border and text.
MENU_MARGINf
int
Margin in pixels around the item.
MENU_PARENTf
Menu
The menu containing the item.
MENU_PULLRIGHT
Menu
Item’s pullright menu.
MENU_P ULLRIGHT_IMAGEf
Pixrect *, Menu
Modifies appropriate fields in item. Set only.
MENU_P ULLRIGHT_ITEMt
char *, Menu
Modifies appropriate fields in item. Set only.
MENO_RELEASE
(no value)
The item will be automatically destroyed when its parent
menu is destroyed (default for items created inline).
MENU_RELE ASE_I MAGE
(no value)
The string or pixrect associated with the item will be
freed when the item is destroyed.
MENU_RIGHT_MARGINf
int
Margin in addition of MENU_MARGIN on right between
menu’s border and text
MENG_SELECTEDt
boolean
If TRUE, the item is currently selected.
MENU_STRINGf
char *
Item’s string.
MENU_STRING_ITEMf
char *, value
Modifies appropriate fields in item. Set only.
MENU_TYPEf
enum
Get only, returns MENU_ITEM.
MENU_VALOE
caddr_t
Item's value.
#sun
XT microsystems
Revision A, of May 9,1988
Chapter 19 — SunView Interface Summary (Menu Functions ) 341
Table 19-15 Menu Functions
Definition
Description
Menu
menu_create(attributes)
<attribuXe-list> a tt r ibut e s;
Creates and returns the opaque handle for a walking menu.
Menu_item
menu_create_item(attributes)
<attribute-list> attributes;
Creates and returns the opaque handle for a single item
within a walking menu.
void
menu__dest roy (menu__ob j ect)
<Menu or Menu_item> menu ob j ect;
Destroys a menu or menu item.
void
menu_destroy_with_proc (menu__object, destroy proc)
<Menu or Menu_item> menu_ob j ect;
void (*destroy_j?roc)();
The function supplied as dest roy_proc is called before
the menu or menu item is destroyed. Arguments:
de st roy_j?roc (menu_ob j ect, type)
<Menu or Menu_item> menu object;
Menu_attribute type;
type is MENU_MENU for menus, MENU_ITEM for items.
Menu_item
menu__f ind (menu, attributes)
Menu menu;
<attribute-list> attributes;
Returns the first menu item in menu meeting the criteria
specified in attributes.
caddr_t
menu_get (menu_ob ject, attribute[, optional arg])
<Menu or Menu_item> menu object;
Menu_attribute attributes;
caddr_t optional_arg;
Retrieves the value for an attribute of a menu or menu item.
int
menu_set(menu_object, attributes)
<M enu or Menu_item> menu_ob j ec t;
<attribute-list> a tt ribu t e s;
Sets the value of one or more attributes for a menu or menu.
item, attributes is a null-terminated attribute list
caddr t
menu^show(menu, window, event, 0)
Menu menu;
Window window;
Event *event;
Displays the menu, gets a selection from the user, and, by
default, returns the value of the item the user has selected.
window is the handle of the window over which the menu
is displayed; event is the event which causes the menu to
come up. The final argument is currently ignored.
Asun
\r microsystems
Revision A, of May 9, 1988
342 SunView 1 Programmer’s Guide
Table 19-15 Menu Functions—
Continued
Definition
Description
caddr_t menu_show_using__fd (menu, fd, event)
Menu menu;
int fd;
Event *event;
Provided for compatibility with SunWindows 2.0. Allows
you to display a menu within a window using the windowfd.
caddr__t
menu_return_item (menu, menu_item)
Menu menu;
Menu_item menu_item;
Predefined notify proc which, if given as the value for
MENU NOTIFY PROC, causes menu_show () to return
the handle of the selected item, rather than its value.
caddr__t
menu_return_value (menu, menu__item)
Menu menu;
Menu item menu item;
Default notify proc for menus. Causes menu_show ()
to return the value of the selected item.
Asun
Xr microsystems
Revision A, of May 9,1988
Chapter 19 — SunView Interface Summary (Notifier Functions) 343
Table 19-16 Notifier Functions
Definition
-I
Description
Notify__value
Predefined function you can register with the Notifier via the
notify_default_wait3 (client, pid.
status, rusage)
notify_set_wait3_func () call. Causes the required
Notify_client
client;
housekeeping to be performed on the process identified by pid
int
pid;
when it dies. See the wait(2) man page for details of the
union wait
*status;
wait and rusage structures.
struct rusage
*rusage;
Provided to allow programs which are not notification-based to
Notify_error
run in the SunView environment. Called regularly from within
notify_dispatch()
the application’s main loop to allow the Notifier to go once
around its internal loop and dispatch any pending events.
Notify_error
Called once, before the application’s main loop. Enables
not ify__do_dis patch ()
“implicit dispatching,” in which the Notifier dispatches
events from within calls to read(2) or select(2).
Notify_error
notify_interpose_destroy_func(client, destroy func)
Interposes destroy_f unc () in front of
Notify_client
client;
client’s destroy event handler.
Notify__func
destroy_func;
Notify__error
notify_interpose__event_func (client
t
event_
func, type)
Interposes event_func () in front of
Notify_client
client;
client’s event handler.
Notify_func
event_func;
Notify_event_type type;
Notify_error
notify_itimer_value(client, which.
value)
Returns the current state of an interval timer for client in the
Notify_client
client;
structure pointed to by value. The which parameter
int
which;
is either ITIMER_REAL or ITIMER_VIRTUAL.
struct itimerval *value;
Notify_value
notify_next_destroy_func (client, status)
Calls the next destroy event handler for client.
Notify_client
client;
status returns DESTROY_PROCESS DEATH,
Destroy_status
status;
DESTROY_CHECKING, or DESTROY_CLEANUP.
microsystems
Revision A, of May 9,1988
344 Sun View 1 Programmer’s Guide
Table 19-16 Notifier Functions — Continued
Definition
Description
Notify_value
notify next_event_func(client, event, arg, type)
Notify_client client;
Event *event;
Notify_arg arg;
Notify_event_type type;
Calls the next event handler for client.
Notify__error
notify_no_dispatch ()
Prevents the Notifier from dispatching events from within the
call to read(2) or select(2).
void
notify_perror(s)
char *s;
Analogous to the UNIX perror(3) system call,
s is printed to stderr, followed by a terse description of
notify_errno ().
Notify_func
notify set_destroy_func (client, destroy_func)
Notify_client client;
Not i f y_func de st roy_func;
Registers destroy_func () with the Notifier.
destroy func () will be called when a
destroy event is posted to client or when the process
receives a SIGTERM signal.
Notify_func
Registers the exception handler exception_func ()
notify_set_exception_func (client, exception_func, fd) with the Notifier. The only known devices that generate
Notify__client client;
Notify_func exception_func;
int fd;
exceptions at this time are stream-based socket
connections when an out-of-band byte is available.
Notify_func
notify set_input_func(client, input_func, fd)
Notify client client;
Notify_func input_func;
int fd;
Registers input__f unc () with the Notifier.
input func () will be called whenever
there is input pending on f d.
Notify_func
notify_set_itimer_func (client, itimer_func, which. Registers the timeout event handler itimer_func ()
value, ovalue)
Notify_client client;
Notify__func itimer_func;
int which;
struct itimerval *value, *ovalue;
with the Notifier. The semantics of which, value
and ovalue parallel the arguments to setitimer
(see the getitimer manual page),
which is either ITIMER_REAL or ITIMER_VIRTUAL.
Asun
\T microsystems
Revision A, of May 9,1988
Chapter 19 — SunView Interface Summary (Notifier Functions) 345
Table 19-16 Notifier Functions — Continued
Definition
Description
Notify_func
notify_set__signal__func (client, signal_func,
signal, when)
Notify_client client;
Notify__func signal_func;
int signal;
Notify_signal_mode when;
Registers the signal event handler signal_func () with
the Notifier. signal_f unc () will be called whenever
signal is caught by the Notifier. when can be either
NOTIFY_SYNC or NOTIFY_ASYNC.
Calling not if y_set_signal_func () with a NULL in the
place of the signal_func () turns off checking for that
signal for that client.
Notify__error
notify_start()
Begins dispatching of events by the Notifier.
Notify_error
notify_stop ()
Terminates dispatching of events by the Notifier.
Notify_func
not if y_set_output_func (client, output_func, fd) Registers out put_func () with the Notifier.
Notify_client client;
Notify_func output_func;
int fd;
output_f unc () will be called whenever
output has been completed on f d.
Notify_func
notify_set_wait3_func(client, wait3 func, pid)
Notify_client client;
Notify_func wait3_func;
int pid;
Registers the function wait3__func () with the Notifier.
The registered function will be called after the child
process identified by pid dies. To do the minimum
processing, register the predefined function
notify_default_wait3 ().
Notify error
notify_veto_destroy(client)
Notify_client client;
Called from within a destroy event handler when status
is DESTROY_CHECKING and the application does not
want to be destroyed.
Asun
\r microsystems
Revision A, of May 9, 1988
346 SunView 1 Programmer’s Guide
Table 19-17 Panel Attributes
Attribute
Value Type
Description
PANEL_ACCEPT_KEYSTROKE
boolean
If TRUE, keystroke events are passed
to the panel’s PANEL_BACKGROUND_PROC. Default: FALSE.
PANEL_BACKGROUND_PROC
(procedure)
Event handling procedure called when an
event falls on the background of the panel. Form:
background_proc(panel, event)
Panel panel
Event *event
PANE L_BLINK_CARET
boolean
If TRUE, the caret blinks. Default: setting of Blink caret in the Text
category of defaultsedit.
PANEL_CARET_ITEM
Panel_item
Text item which currently has the caret.
Default: first text item.
PANEL_EVENT_PROC
(procedure)
Event handling procedure for panel items.
Sets the default for subsequent items created in panel. Form:
event_proc(item, event)
Panel_item item
Event *event
PANE L_FIRST_ITEM
Panel_item
First item in the panel. Get only.
P ANEL_I TEM_X_GAP
int
Number of x-pixels between items. Default: 10.
PANEL_ITEM_Y_GAP
int
Number of y-pixels between items. Default: 5.
PANEL_LABEL_BOLD
boolean
If TRUE, item’s label is rendered in bold.
Sets the default for subsequent items created in panel. Default: FALSE.
PANEL_LAYOUT
Panel_setting
Layout of item’s value relative to the label.
PANEL_HORI ZONTAL (default) or PANEL_VERTICAL.
PANEL_SHOW_MENU
boolean
If TRUE, the menu for the item is enabled.
Sets the default for subsequent items created in panel.
Revision A, of May 9,1988
Chapter 19 — SunView Interface Summary (Panel Generic Item Attributes) 347
Table 19-18 Generic Panel Item Attributes
Attribute
Value Type
Description
PANEL_ACCEPT_KEYSTROKE
boolean
If TRUE, keystroke events are passed to the item’s EVENT PROC.
PANEL_CLIENT_DATA
caddr_t
For application’s use.
PANEL_EVENT_PROC
(procedure)
Event handling procedure for the item.
PANEL_ITEM_RECT
Rect *
Enclosing rectangle for the item. Get only.
PANEL_ITEM_X
int
Left edge of item rectangle. If unspecified and label or value positions are
fixed, then set to min of PANEL_LABEL_X and PANEL_VALUE X.
Default: after lowest, rightmost item
PANEL_ITEM_Y
int
top edge of item rectangle. If unspecified and label or value positions are
fixed, then set to min of PANEL_LABEL_Y and PANEL VALUE Y.
Default: previous item’s PANEL ITEM Y.
PANEL__LABEL_X
int
Left edge of label. If unspecified and value position is fixed, then set to
left of PANEL_VALUE_X for horizontal layout, or at PANEL_VALUE X
for vertical layout. Default: PANEL ITEM X.
PANEL_LABEL_Y
int
Top edge of label. If unspecified and value position is fixed, then set to
PANEL_VALUE_Y for horizontal layout, or above PANEL VALUE Y
for vertical layout. Default: PANEL_ITEM Y.
PANEL_LABEL_BOLD
boolean
If TRUE, item’s label is rendered in bold. Default: FALSE.
PANEL_LABEL_FONT
Pixfont *
Font for PANEL_LABEL_STRING. Default: WIN_FONT.
PANEL__LABEL_IMAGE
Pixrect*
Image for item’s label.
PANEL_LABEL_STRING
char *
String for item’s label.
P ANEL_LAY OUT
Panel_setting
Layout of item’s value relative to the label. PANEL HORIZONTAL
(default) or PANEL_VERT I CAL.
PANE L_MENU_CHOICE_FONTS
list of Pixfont *
Font for each menu choice string. Create, set. Default: WIN FONT.
PANE L_MEN U__CHO I CE_I MAGE S
list of Pixrect *
Image for each menu choice. Create, set. Default:
PANEL_CHOICE_IMAGES for choice items, PANEL LABEL IMAGE
for button items, NULL for other items.
PANEL_MENU_CHOICE_STRINGS
list of char *
String for each menu choice. Create, set. Default:
PANEL_CHOICE_STRINGS for choice items, NULL for other items.
PANE L_MENU_CHOICE_VALUES
list of caddr_t
The values returned from the item’s menu. Create, set
microsystems
Revision A, of May 9, 1988
348 SunView 1 Programmer’s Guide
Table 19-18 Generic Panel Item Attributes — Continued
Attribute
Value Type
Description
PANEL_MENU_TITLE_FONT
Pixfont *
Font for PANEL_MENU_TITLE_STRING.
PANEL_MENUJTITLE_IMAGE
Pixrect *
Image for the menu title.
PANEL_MENU_TITLE_STRING
char *
String for the menu title.
PANEL_NEXT_ITEM
Panel_item
Next item in the panel. Get only.
PANEL_NOTIFY_PROC
(procedure)
Function to call when item is selected. Form for button and text items:
notify_j?roc (item, event)
Panel_item item
Event *event
Choice and slider items have an additional parameter for the current value:
notify__proc (item, value, event)
Panel_item item
int value
Event *event
For toggle items, the value parameter is of type unsigned int.
The type for a text item notify_j?roc is Panel__setting.
PANEL_PAINT
Panel_setting
Item’s painting behavior for panel__set () calls. One of:
PANEL_NONE, PANEL_CLEAR, or PANEL_NO_CLEAR
PANEL_PARENT_PANEL
Panel
The panel which contains the item.
PANEL_SHOW_ITEM
boolean
Whether or not to show the item. Default: TRUE.
PANEL_SHOW_MENU
boolean
If TRUE, the menu for the item is enabled.
PANEL_VALOE_X
int
Left edge of value. If unspecified and label position is fixed,
then set to right of PANEL__LABEL_X for horizontal layout, or
at PANEL LABEL X for vertical layout. Default: after the label.
PANEL_VALOE_Y
int
Top edge of value. If unspecified and label position is fixed, then set
to PANEL LABEL Y for horizontal layout, or below
PANEL LABEL Y for vertical layout. Default: PANEL_LABEL_Y.
#sun
XT microsystems
Revision A, of May 9, 1988
Chapter 19 — SunView Interface Summary Q Panel Choice and Toggle Item Attributes) 349
Table 19-19 Choice and Toggle Item Attributes
....
n - j
Attribute
Value Type
Description
PANEL_CHOICE_FONTS
list of Pixfont *
Font to use for each choice string. Create, set.
PANEL_CHOICE_IMAGE
int, pixrect *
Image for choice specified by the first argument.
PANEL_CHOICE_IMAGES
list of Pixrect *
Image for each choice. Create, set.
PANEL_CHOICE_STRING
int, char *
String for choice specified by first argument.
PANEL_CHOICE_STRINGS
list of char *
String for each choice. Note that you must specify at
least one choice — the least you can specify is a single
null string (PANEL_CHOICE_STRINGS, 0).
Create, set.
PANEL_CHOICE_X
int, int
Second argument is left edge of choice specified by first
argument.
PANEL_CHOICE_XS
list of int
Left edge of each choice. Create, set.
PANEL_CHOICE_Y
int, int
Second argument is top edge of choice specified by first
argument.
PANEL_CHOICE_YS
list of int
Top edge of each choice. Create, set.
PANEL_CHOICES_BOLD
boolean
If TRUE, choices strings are in bold. Default: FALSE.
PANEL_DISPLAY_LEVEL
Panel_setting
How many choices to display. One of PANEL_NONE,
PANEL_CURRENT, or PANEL_ALL. Default:
PANEL_ALL.
PANEL_FEEDBACK
Panel_setting
Feedback to give when a choice is selected. One of
PANEL_NONE, PANEL_MARKED,
PANEL_INVERTED. If PANEL__DISPLAY_LEVEL is
PANEL CURRENT, default is PANEL_NONE, otherwise
PANEL_MARKED.
PANEL_LAYOUT
Panel_setting
Layout of the choices: PANEL_HORIZONTAL (default)
or PANEL_VERT I CAL.
PANEL_MARK_IMAGE
int, Pixrect *
Image to mark choice specified by the first argument
when it is selected. Default is push-button image:
<images/panel__choice_on. pr>.
Revision A, of May 9, 1988
350 SunView 1 Programmer’s Guide
Table 19-19
Choice and Toggle Item Attributes — Continued
Attribute
Value Type
Description
P ANEL_MARK_I MAGE S
list of Pixrect *
Image to mark each choice with when selected. Create,
set only. Default is push-button image:
<images/panel_choice_on.pr>.
P ANE L_MARK_X
int, int
Second argument is left edge of choice mark specified by
first argument.
PANEL_MARK_XS
list of int
Left edge of each choice mark. Create, set.
PANEL_MARK_Y
int, int
Second argument is top edge of choice mark specified by
first argument.
PANEL_MARK_YS
list of int
Top edge of each choice mark. Create, set.
PANEL_MENU_MARK_IMAGE
Pixrect *
Image to mark each menu choice with when selected.
P ANEL_MENU_NOMARK_I MAGE
Pixrect *
Image to mark each menu choice with when not selected.
PANEL_NOMARK_IMAGE
IP
int, Pixrect *
Image to mark choice specified by the first argument
when it is not selected. Default is push-button image:
<images/panel_choice off.pr>.
PANEL_NOMARK_IMAGES
list of Pixrect *
Image to mark each choice with when not selected.
Create, set. Default is push-button image:
<images/panel_choice__of f. pr>.
PANEL_SHOW_MENU_MARK
boolean
Show or don’t show the menu mark for each selected
choice. Default: TRUE.
PANEL_TOGGLE__VALUE
int, int
Value of a particular toggle choice. Second argument is
value of choice specified by first argument
PANEL_VALUE
int or unsigned
If item is a choice, value is ordinal position (from 0) of
current choice. If item is a toggle, value is a bitmask
indicating currently selected choices (e.g., bit 5 is 1 if
5th choice selected).
microsystems
Revision A, of May 9, 1988
Chapter 19 — SunView Interface Summary (Panel Slider Item Attributes) 351
Table 19-20
Slider Item Attributes
Attribute
Value Type
Description
PANEL_MIN_VALUE
int
Minimum value of slider. Default: 0.
PANE L_MAX_VALUE
int
Maximum value of the slider. Default: 100.
PANEL_NOTIFY_LEVEL
Panel_setting
When to call the notify function: PANEL_DONE notifies when the
select button is released, P ANEL_ALL notifies continuously as the
select button is dragged. Default: PANEL_DONE.
PANE L_SH OW_RAN GE
boolean
Show or don’t show the min and max slider values. Default: TRUE.
PANE L_SHOW_VALUE
boolean
Show or don’t show integer value of slider. Default: TRUE.
PANEL_SLIDER__WI DTH
int
Width of the slider bar in pixels. Default: 100.
PANEL_VALUE
int
Initial or new value for the item, in the range
P ANE L_M I N_VAL UE to PANE L_MAX_VALUE. Default:
PANEL_MIN_VALUE.
PANEL_VALUE_FONT
Pixfont *
Font to use when displaying the value.
microsystems
Revision A, of May 9, 1988
352 SunView 1 Programmer’s Guide
Table 19-21
Text Item Attributes
Attribute
Value Type
Description
P ANE L_MAS K_CHAR
char
Character used to mask type-in characters. Use the space character
for no character echo (caret does not advance). Use the null char¬
acter to disable masking.
PANEL_NOTIFY_LEVEL
Panel_setting
When to call the notify function. One of PANEL_NONE,
PANEL_NON_PRINTABLE, PANEL_SPECIFIED, or
PANEL_ALL. Default: PANEL_SPECIFIED (see Text
Notification).
PANEL_NOTIFY_STRING
char *
String of characters which trigger notification when typed.
Applies only when PANEL_NOTIFY_LEVEL is
PANEL__SPECIFIED. Default: \n\r\t (newline, carriage return
and tab).
PANEL_VALUE_STORED__LENGTH
int
Max number of characters to store in the value string. Default: 80.
P ANEL_VALUE_DI SPLAY__LENGTH
int
Max number of characters to display in the panel. Default: 80.
PANEL_VALUE
char *
Initial or new string value for the item.
PANEL VALUE F ONT
Pixfont *
Font to use for the value string.
microsystems
Revision A, of May 9, 1988
Chapter 19 — SunView Interface Summary (Panel Functions and Macros) 353
Table 19-22 Panel Functions and Macros
m
■
■
m
1
1
1
1
I
m
1
M-
———
Definition
Description
panel_accept_key(object, event)
<Panel or Panel_item> object ;
Event *event;
Action function which tells a text item to accept a keyboard event.
Currently ignored by non-text panel items.
panel_accept_menu(object, event)
<Panel or Panel_item> object;
Event *event;
Action function which tells an item to display its menu and process
the user’s selection.
panel_accept_preview(object, event)
<Panel or Panel_item> object ;
Event *event;
Action function which tells an item to do what it is supposed to do
when it is selected. This may include completing feedback
initiated by panel_begin_preview ().
Panel__item
panel_advance_caret(panel)
Panel panel;
Advance the caret to the next text item. If on the last
text item, rotate back to the first. Returns the new
caret item, or NULL if there are no text items.
Panel_item
panel_backup_caret(panel)
Panel panel;
Backup the caret to the previous text item. If on the
first text item, rotate back to the first. Returns the
new caret item, or NULL if there are no text items.
panel_begin_preview(object, event)
<Panel or Panel_item> object ;
Event *event;
Action function which tells an item to begin any feedback which
indicates tentative selection.
Pixrect *
panel_button_image (panel, string, width, font) Creates a standard, button-like image from a string. The string is
Panel panel;
char *string;
int width;
Pixfont *font;
rendered in font, centered within a double-pixel border width
characters wide. If width is too narrow for the string, the border
will be expanded to contain the entire string. If font is 0,
panel’s font is used.
panel__cancel_preview (object, event)
<Panel or Panel_item> object ;
Event *event;
Action function which tells an item to cancel the feedback initiated
by panel_begin_jpreview ().
Panel_item
Creates and returns the opaque handle to a panel item. item__type
panel_create_item(panel, item_type, attributes) is one of: PANEL_MESSAGE, PANEL_BUTTON, PANEL_CHOICE,
Panel panel;
<itemtype> item_type;
<attribute-list> attributes;
PANEL_CYCLE, PANEL_TOGGLE, PANELJTEXT or
PANEL_SLIDER. attributes is a null-terminated attribute list.
Asun
\r microsystems
Revision A, of May 9, 1988
354 SunView 1 Programmer’s Guide
Table 19-22 Panel Functions and Macros — Continued
Definition
Description
panel default__handle_event(object, event)
<Panel or Panel_item> object ;
Event *event;
The default event proc for panel items (PANEL_EVENT_PROC)
and for the panel’s background (PANEL_BACKGROUND_PROC).
Implements the standard event-to-action mapping for the item types.
panel destroy_item(item)
Panel__item item;
Destroys item.
panel_each_item (panel, item)
Panel panel;
Panel_item item;
Macro to iterate over each item in a panel. The corresponding macro
panel_end_each closes the loop opened by
panel_each_item().
Event *
panel_event (panel, event)
Panel panel;
Event *event;
Translates the coordinates of event from the space of the panel
subwindow to the space of the logical panel
(which may be larger and scrollable).
caddr__t
panel_get(item, attribute[, optional_arg])
Panel_item item;
Panel_attribute attribute;
Panel_attribute optional_arg;
Retrieve the value of an attribute for item. optional__arg is
used for a few attributes which require additional information,
such as PANEL__CHOI CE_IMAGE, PANEL_CHOICE_STRING,
P ANEL_CHO I CE_X, PANEL_CHOICE_Y,
PANEL_MARK_X, PANEL_MARK__Y, PANEL_TOGGLE_VALUE.
caddr_t
panel get_value (item)
Panel__item item;
A macro, defined as:
panel_get (item, PANEL_VALUE)
panel_paint(panel_object, paint_behavior)
<Panel_item or Panel> panel_ob j ect;
Panel_setting paint_behavior;
Paints an item or an entire panel. paint_behavior can be either
PANEL_CLEAR or PANEL_NO_CLEAR. PANEL_CLEAR causes
the area occupied by the panel or item to be cleared prior to painting.
panel_set(item, attributes)
Panel_item item;
<attribute-list> att ribut e s;
Sets the value of one or more panel attributes,
attributes is a null-terminated attribute list.
panel set_value(item, value)
Panel_item item;
caddr__t value;
A macro, defined as:
panel__set (item, PANEL_VALUE, value, 0)
Panel_setting
panel_text_notify(item, event)
Panel item item
Event *event
Default notify procedure for panel text items. Causes caret
to advance on CR or tab, caret to backup on shift-CR or shift-tab,
printable characters to be inserted into item's value,
and all other characters to be discarded.
Asun
xr microsystems
Revision A, of May 9, 1988
Chapter 19 — SunView Interface Summary (Panel Functions and Macros) 355
Table 19-22
Panel Functions and Macros — Continued
Definition
Description
panel_update_preview(object,
<Panel or Panel_item> object ;
Event *event;
event)
Action function which tells the item to update its previewing
feedback (e.g. redraw the slider bar for a slider item).
panel_update_scrolling size(panel)
Panel panel;
Updates the scrollbar’s notion of the panel’s size,
so the scrollbar’s bubble will be the correct size.
Event *
panel__window__event (panel, event)
Panel panel;
Event *event;
Translates the coordinates of event to the space of the panel
subwindow from the space of the logical panel
(which may be larger and scrollable).
microsystems
Revision A, of May 9,1988
356 SunView 1 Programmer’s Guide
Table 19-23 Pixwin Drawing Functions and Macros
Definition
Description
pw_batch(pw, n)
Pixwin *pw;
Pw batch_type n;
Tells the batching mechanism to refresh the screen every
n display operations.
pw_batch_off(pw)
Pixwin *pw;
A macro to turn batching off in pw.
pw_bat ch_on(pw)
Pixwin *pw;
A macro to turn batching on in pw.
pw batchrop(pw, dx, dy, op, items, n)
Pixwin *pw;
int dx, dy, op, n;
struct pr_prpos items[];
See the Pixrect Reference Manual for a full explanation
of this function.
pw char(pw, x, y, op, font, c)
Pixwin *pw;
int x, y, op;
Pixfont *font;
char c;
Writes character c into pw using the rasterop op.
The left edge and baseline of c will be written at
location (x, y).
pw_close(pw)
Pixwin *pw;
Frees any dynamic storage associated with pw,
including its retained memory pixrect, if any.
pw_copy(dpw, dx, dy, dw, dh,
op, spw, sx, sy)
Pixwin *dpw, *spw;
int op, dx, dy, dw, dh, sx, sy;
Copies pixels from spw to dpw. Currently spw and
dpw must be the same. This routine will cause problems if
spw is obscured.
int
pw_get(pw, x, y)
Pixwin *pw;
int x, y;
Returns the value of the pixel at (x, y) in pw.
int
pw_get_region_rect (pw, r)
Pixwin *pw;
Rect *r;
Retrieves the rectangle occupied by the region pw
into the rect pointed to by r.
Asun
xr microsystems
Revision A, of May 9,1988
Chapter 19 — SunView Interface Summary (Pixwin Drawing Functions and Macros) 357
Table 19-23 Pixwin Drawing Functions and Macros — Continued
Definition
Description
pw__line(pw, xO, yO, xl, yl, brush, tex, op)
Pixwin *pw;
int xO, yO, xl, yl, op;
struct pr_brush *brush;
struct pr_texture *tex;
Draws a solid or textured line between two points with a
“brush” of a specified width.
pw lock(pw, r)
Pixwin *pw;
Rect *r;
Acquires a lock for the user process making the call,
r is the rectangle in pw’s coordinate system
that bounds the area to be affected.
pw_jpf sysclose ()
Closes the system font opened with pw_pf sysopen ().
Pixfont *
pw_jpf sysopen ()
Opens the system font.
pw_j?olygon_2(pw, dx, dy f nbds, npts.
vlist, op f spr, sx, sy)
Pixwin *pw;
int dx, dy, nbds, op, sx, sy; Draws a polygon in pw.
int npts[];
struct pr_pos *vlist;
Pixrect *spr;
pw_polyline(pw, dx, dy, npts,
ptlist, mvlist, brush, tex, op)
Pixwin
*pw;
int
dx, dy, npts, op;
Draws multiple lines of a specified width and texture in
struct
pr_pos
*ptlist;
pw.
u__char
*mvlist;
struct
pr_brush
*brush;
struct
pr_texture
*tex;
pw_polypoint(pw, dx, dy, npts, ptlist, op)
Pixwin *pw; _ _ .....
Draws an array of npts points m the pixwm pw
int dx, dy, npts, op;
struct pr_pos *ptlist;
pw_put(pw, x, y, value)
Pixwin *pw; Draws a pixel of value at (x, y) in pw.
int x, y, value;
Revision A, of May 9, 1988
358 SunView 1 Programmer’s Guide
Table 19-23 Pixwin Drawing Functions and Macros — Continued
Definition
Description
pw__read(pr, dx, dy, dw, dh, op, pw, sx, sy)
Pixwin *pw;
int op, dx, dy, dw, dh, sx, sy;
Pixrect *pr;
Reads pixels from the pixwin pw starting at offset (sx,
sy), using rasterop op. The pixels are stored in the rec¬
tangle (dx, dy, dw, dh) in the pixrect pointed to by pr.
Pixwin *
pw_region(pw, x, y, width, height)
Pixwin *pw;
int x, y, w, h;
Creates a new pixwin refering to an area within the existing
pixwin pw. The origin of the new region is given by (x,
y), the dimensions by width and height.
pw_replrop(pw, dx, dy, dw, dh,
op, pr, sx, sy)
Pixwin *pw;
int dx, dy, dw, dh, op, sx, sy;
Pixrect *pr;
Replicates a pattern from a pixrect into a pixwin.
pw_reset(pw)
Pixwin *pw;
Macro which sets pw’s lock count to 0 and releases its lock.
pw_rop(pw, dx, dy, dw, dh,
op, sp, sx, sy)
Pixwin *pw;
Pixrect *sp;
int dx, dy, dw, dh, op, sx, sy;
Performs the rasterop op from the source pixrect
sp to the destination pixwin pw.
int
pw_set_region_rect (pw, r, use_same_pr)
Pixwin *pw;
Rect *r;
unsigned int use_same_j?r;
The position and size of the region pw are set to the rect
*r.
If use_same_pr is 0 a new retained pixrect is allocated
for the region.
pw_show(pw)
Pixwin *pw;
Macro to refresh the screen while batching, without affect¬
ing the batching mode.
pw__stencil (dpw, dx, dy, dw, dh, op,
stpr, stx, sty, spr, sx, sy)
Pixwin *dpw;
int dx, dy, dw, dh, op, stx, sty, sx, sy;
Pixrect *stpr, *spr;
Like pw_write (), except that the source pixrect spr is
written through the stencil pixrect stpr, which functions
as a spatial write enable mask. The raster operation op is
only applied to destination pixels where the stpr is non¬
zero; other destination pixels remain unchanged.
pw_text(pw, x, y, op, font, s)
Pixwin *pw;
int x, y, op;
Pixfont *font;
char *s;
Writes the string s into pw using the rasterop op.
The left edge and baseline of the first character in s will
appear at coordinates (x, y).
sun Revision A, of May 9,1988
microsystems
Chapter 19 — SunView Interface Summary (Pixwin Drawing Functions and Macros) 359
Table 19-23 Pixwin Drawing Functions and Macros — Continued
Definition
Description
pw_traprop(pw, dx, dy f t, op, pr f sx, sy)
Pixwin *pw;
struct pr_trap t;
Pixrect *pr;
int dx, dy, op, sx, sy;
Like pw_rop (), but operating on a trapezon rather than a
rectangle.
pw_ttext(pw, x, y, op, font, s)
Pixwin *pw;
int x, y, op;
Pixfont *font;
char *s;
Like pw_text () except that it writes “transparent” text,
i.e. it writes the shape of the letters without disturbing the
background behind the letters.
pw_unlock(pw)
Pixwin *pw;
Decrements the lock count for pw. If the lock count goes
to 0, the lock is released.
pw_vector(pw, xO, yO, xl, yl, op, value)
Pixwin *pw;
int op, xO, yO, xl, yl, value;
Draws a vector of pixel value from (xO, yO) to (xl,
yl)in pw using rasterop op.
pw_write(pw, dx, dy, dw, dh,
op, pr, sx, sy)
Pixwin *pw;
int dx, dy, dw, dh, op, sx, sy;
Pixrect *pr;
Writes pixels to pw in the rectangle defined by dx, dy,
dw, dh, using rasterop op. Pixels to write are taken from
the rectangle with its origin at sx, sy in the source pix¬
rect pointed to by pr.
Note: this is an alternative form of pw_rop.
pw_writebackground(pw, dx, dy, dw, dh, op)
Pixwin *pw;
int dx, dy, dw, dh, op;
Writes pixels with value zero into pw using the rasterop op.
xd, yd, width and height specify the rectangle in
pw which is affected.
A sun
microsystems
Revision A, of May 9, 1988
360 SunView 1 Programmer’s Guide
Table 19-24 Pixwin Color Manipulation Functions
mm.
Definition
Description
pw_blackonwhite(pw, min, max)
Pixwin *pw;
int min, max;
Sets the foreground to black, the background to white, for pixwin
pw. min and max should be the first and last entries, respectively,
in pw’s colormap segment.
pw cyclecolormap(pw, cycles, index,
Pixwin *pw;
int cycles, index, count;
count)
Rotates the portion of pw’s colormap segment starting at index
for count entries, rotating those entries among themselves
cycles times.
pw_dbl_access (pw)
Pixwin *pw;
Resets the window’s data structure so that the first frame will be ren¬
dered to the background.
pw dbl_flip(pw)
Pixwin *pw;
Allows you to flip the display.
pw_dbl_get(pw, attribute)
Pixwin *pw;
Pw__dbl_at tribute attribute;
Retrieves the value of the specified attribute.
pw_dbl_release ()
Pixwin *pw;
Signifies the end of double-buffering by the window associated with
the pixwin.
pw_dbl_set(pw, attributes)
Pixwin *pw;
<attribute- list> attributes;
Sets the pixwin hardware double-buffering attributes in attri¬
butes.
pw_getattributes(pw, planes)
Pixwin *pw;
int *planes;
Retrieves the value of pw’s access enable mask
into the integer addressed by planes.
pw_getcmsname(pw, cmsname)
Pixwin *pw;
char cmsname [CMS_NAMESIZE];
Copies the colormap segment name of pw into cmsname.
pw_getcolormap(pw, index, count,
red, green, blue)
Pixwin *pw;
int index, count;
unsigned char red[], green[],
blue[];
Retrieves the state of pw’s colormap. The count elements
of the pixwin’s colormap segment starting at index
(0 origin) are loaded into the first count values in the
three arrays.
®sun
Xr microsystems
Revision A, of May 9, 1988
Chapter 19 — SunView Interface Summary (Pixwin Color Manipulation Functions) 361
Table 19-24 Pixwin Color Manipulation Functions — Continued
Definition
Description
pw_getdefauItems (ems, map)
struct colormapseg *cms;
struct cms_map *map;
Copies the data in the default colormap segment into
the data pointed to by ems and map. Before the call, the byte pointers
in map should be initialized to arrays of size 256.
pw__putattributes (pw, planes)
Pixwin *pw;
int *planes;
Sets the access enable mask of pw. Only those bits of the pixel
corresponding to a 1 in the same bit position of *planes will be
affected by pixwin operations.
pw_j?utcolormap (pw, index, count,
red, green, blue)
Pixwin *pw;
int index, count;
unsigned char red[], green[], blue[];
Sets the state of pw’s colormap. The count elements of the
pixwin’s colormap segment starting at index (0 origin) are loaded
from the first count values in the three arrays.
pw_reversevideo(pw, min, max)
Pixwin *pw;
int min, max;
Reverses the foreground and background colors of pw
min and max should be the first and last entries,
respectively, in the colormap segment.
pw_setcmsname(pw, emsname)
Pixwin *pw;
char emsname [CMS_NAMESIZE];
emsname is the name that pw will call its window’s
colormap segment. This call resets the colormap segment to NULL.
pw_whiteonblack(pw, min, max)
Pixwin *pw;
int min, max;
Sets the foreground to white, the background to black, for pw.
min and max should be the first and last entries, respectively, in the
colormap segment.
#sun
\r microsystems
Revision A, of May 9, 1988
362 SunView 1 Programmer’s Guide
Table 19-25
Scrollbar Attributes
Attribute
Value Type
Description
SCROLL_ABSOLUTE_CURSOR
Cursor
Cursor to display on middle button down.
Default: Right triangle if vert., down triangle if horiz.
SCROLL_ACTIVE_CURSOR
Cursor
Cursor to display when cursor is in bar rect.
Default: Right arrow if vertical, down arrow if horiz.
SCROLL_ADVANCED_MODE
boolean
Whether notify proc reports all nine motions. Default: FALSE.
SCROLL_BACKWARD_CURSOR
Cursor
Cursor to display on right button down.
Default: up arrow if vertical, left arrow if horiz.
SCROLL_BAR_COLOR
Scrollbar_setting
Color of bar, SCROLL_GREY (default) or SCROLL_WHITE.
SCROLL_BAR_DISP LAY_LEVEL
Scrollbar_setting
When bar is displayed.
SCROLL_ALWAYS: always displayed
SCROLL ACTIVE: only displayed when cursor is in bar rect
SCROLL NEVER: never displayed
Default: SCROLL_ALWAYS.
SCROLL_BORDER
boolean
Whether the scrollbar has a border.
SCROLL_BUBBLE_COLOR
Scrollbar_setting
Color of bubble, SCROLL_GREY (default) or SCROLL_BLACK.
SCROLL_BUBBLE_DISPLAY_LEVEL
Scrollbar_setting
When bubble is displayed.
SCROLL_ALWAYS: always displayed
SCROLL ACTIVE: only displayed when cursor is in bar rect
SCROLL_NEVER: never displayed
Default: SCROLL_ALWAYS.
SCROLL_BUBBLE_MARGIN
int
Margin on each side of bubble in bar. Default: 0.
SCROLL_DIRECTION
Scrollbar_setting
Orientation of bar,
SCROLL_VERT ICAL (default) or SCROLL_HORI ZONTAL.
SCROLL_END_POINT_AREA
int
The distance, in pixels, from the end of the scrollbar
that forces a scroll to the beginning (or end) of the file.
Default: 6.
SCROLL_FORWARD_CURSOR
Cursor
Cursor to display on left button down.
Default: down arrow if vertical, right arrow if horiz.
SCROLL_GAP
int
Gap between lines. Default: current value of SCROLL_MARGIN.
Revision A, of May 9, 1988
Chapter 19 — SunView Interface Summary (Scrollbar Attributes) 363
Table 19-25 Scrollbar Attributes — Continued
Attribute
Value Type
Description
SCROLL_HEIGHT
int
r_height for scrollbar’s rect.
SCROLLJLAST_VIEW_START
int
Offset of view into object prior to scroll. Get only.
SCROLL__LEFT
int
r_lef t for scrollbar’s rect.
SCROLL__L I NE_HE I GHT
int
Number of pixels from one line to the next.
Default: 0.
SCROLL_MARGIN
int
Top margin after scroll, if SCROLL_NORMALIZE TRUE.
Default: 4.
SCROLL_MARK
int
Position (in client units) undo will go to. Initial value: 0.
SCROLL_NOTIFY_CLIENT
caddr_t
Used by Notifier.
SCROLL_NORMALIZE
boolean
Whether the client wants normalized scrolling. Default: TRUE.
SCROLLJDBJECT
caddr_t
Pointer to the scrollable object.
SCROLL_OBJECT_LENGTH
int
Length of scrollable object, in client units. Default: 0.
(Value must be > 0).
SCROLL_PAGE_BUTTONS
boolean
Whether the scrollbar has page buttons. Default: TRUE.
SCROLL_PAGE_BUTTON_LENGTH
int
Length in pixels of page buttons. Default: 15.
SCROLL_PAINT_BUTTONS_PROC
(procedure)
Procedure which paints page buttons:
paint_buttons_j?roc (scrollbar)
Scrollbar scrollbar;
Setting the value to NULL resets it to the default button painting
procedure.
SCROLL_PIXWIN
Pixwin *
Pixwin for scrollbar to write to.
SCROLL_PLACEMENT
Scrollbar_setting
Placement of the bar.
SCROLL_WEST: vertical bar on left edge
SCROLL_EAST: vertical bar on right edge
SCROLL_NORTH: horizontal bar on top edge
SCROLL_SOUTH: horizontal bar on bottom edge
Default: SCROLL__WEST or SCROLL_NORTH.
SCROLL_RECT
Rect *
Rect for scrollbar, including buttons.
Revision A, of May 9, 1988
364 SunView 1 Programmer’s Guide
Table 19-25 Scrollbar Attributes—Continued
Attribute
Value Type
Description
SCROLL_REPEAT_T IME
int
The interval, in tenths of a second, that scrolling
repeats in. This attribute is used only for the initial pressing down
of the mouse. A value of 0 disables repeat scrolling. Default: 10.
SCROLL_REQUEST_MOTION
Scroll_motion
Scrolling motion requested by user.
SCROLL_REQUEST_OFFSET
int
Pixel offset of scrolling request into scrollbar. Default: 0.
SCROLL_THICKNESS
int
Thickness of bar. Default: 14.
SCROLL_TO_GRID
boolean
Whether the client wants scrolling aligned to multiples
of SCROLL_LINE__HEIGHT. Default: FALSE.
SCROLL_TOP
int
r_top for scrollbar’s rect.
SCROLL_VIEW_LENGTH
int
Length of viewing window, in client units. Default: 0.
SCROLL_VIEW_START
int
Current offset into scrollable object (client units).
(Value must be > 0). Default: 0.
SCROLL_WIDTH
int
r width for scrollbar’s recL
©sun
\T microsystems
Revision A, of May 9,1988
Chapter 19 — Sun View Interface Summary (Scrollbar Functions) 365
Table 19-26 Scrollbar Functions
Definition
Description
Scrollbar
scrollbar__c reate (attributes)
<attribute-list> a11ributes;
Creates and returns the opaque handle to a scrollbar.
int
scrollbar_destroy(scrollbar)
Scrollbar scrollbar;
Destroys scrollbar.
caddr t
scrollbar_get(scrollbar, attribute)
Scrollbar scrollbar;
Scrollbar attribute attribute;
Retrieves the value for an attribute of scrollbar.
int
scrollbar_set(scrollbar, attributes)
Scrollbar scrollbar;
<attribute - list> attributes;
Sets the value for one or more attributes of scrollbar.
attributes is a null-terminated attribute list.
void
scrollbar_scroll_to(scrollbar, new_view_start)
Scrollbar scrollbar;
long new_view_start;
For programmatic scrolling. Effect is as if the user had
requested a scroll to new_view_start in the subwin¬
dow to which scrollbar is attached.
int
scrollbar_paint(scrollbar)
Scrollbar scrollbar;
Paints those portions of s c roll bar
(page buttons, bar proper, and bubble)
which have been modified since they were last painted.
int
scrollbar_paint_clear(scrollbar)
Scrollbar scrollbar;
Clears and repaints all portions of scrollbar.
int
scrollbar_clear_bubble(scrollbar)
Scrollbar scrollbar;
Clears the bubble in scrollbar.
int
scrollbar_paint_bubble(scrollbar)
Scrollbar scrollbar;
Paints the bubble in scrollbar.
Revision A, of May 9, 1988
366 SunView 1 Programmer’s Guide
Table 19-27 Text Subwindow Attributes
Attribute
Value Type
Description
TEXTSW_ADJUST_IS_PENDING_DELETE
boolean
When TRUE, adjusting a selection causes the selection to be
pending-delete. Default: FALSE.
TEXTSW_AGAIN_RECORDING
boolean
When FALSE, changes made to the textsw are not repeated when user
invokes AGAIN. By disabling when not needed (e.g. for program-
driven error logs) you can reduce memory overhead. Default: TRUE.
TEXTSW_AUTO_INDENT
boolean
When TRUE, a new line is automatically indented to match
the previous line. Default: FALSE.
TEXTSW_AUTO__SCROLL__BY
int
Number of lines to scroll when type-in moves insert point
below the view. Default: 1. Create, get.
TEXT SW_BL INK__CARET
boolean
Determines whether the caret blinks. Default: TRUE.
TEXTSW_BROWSING
boolean
When TRUE, prevents editing of the displayed text. If another
file is loaded in, browsing stays on. Default: FALSE.
TEXTSW_CHECKPOINT_FREQUENCY
int
Number of edits between checkpoints. Set to 0 to
disable checkpointing. Default: 0.
TEXTSW_CLIENT_DATA
char *
Pointer to arbitrary client data. Default: NULL.
TEXT SW_CONFIRM_OVERWRITE
boolean
A request to write to an existing file will require user
confirmation. Default: TRUE.
TEXTSW_CONTENTS
char*
Contents of text subwindow. Default: NULL.
For create and set, specifies the initial contents for non-file textsw.
Get needs additional parameters:
window_get (textsw, TEXTSW_CONTENTS, pos, buf, bufjen)
Return value is next position to read at.
buf [ 0...buf_len-l ] is filled with the characters from textsw
beginning at index pos, and is null-terminated only if there
were too few characters to fill the buffer.
TEXTSW__CONTROL_CHARS__USE_F ONT
boolean
If FALSE, control characters always display as an
up arrow followed by a character, instead of whatever
glyph is in the current font. Default: FALSE.
TEXTSW_DISABLE_CD
boolean
Stops textsw from changing current working directory
(and grays out the associated items in the menu).
Default: FALSE.
Xr microsystems
Revision A, of May 9,1988
Chapter 19 — SunView Interface Summary (Text Subwindow Attributes) 367
Table 19-27
Text Subwindow Attributes — Continued
Attribute
Value Type Description
TEXTSW_DI SABLE_LOAD
boolean Prevents files being loaded into the textsw (and grays out
the associated items in the menu). Default: FALSE.
TEXTSW_EDIT_COUNT
int Monotonically incrementing count of the number of edits
made to the textsw. Get.
TEXTSW_FILE
char * File to load. Default: NULL. Create, set.
TEXTSW_FILE_CONTENTS
char * initializes the text subwindow contents
from a file yet still edits the contents in memory.
TEXTSW_FIRST
int Zero-based index of first displayed character.
TEXTSW_FIRST_LINE
int Zero-based index of first displayed line.
TEXTSW_HISTORY_LIMIT
int Number of user action sequences that can be undone.
Default: 50. Create, get.
TEXTSW_IGNORE_LIMIT
int Number of edits textsw allows before vetoing destroy. Valid values
are 0, meaning destroy will be vetoed if any edits have been done, and
TEXTSW INFINITY, meaning destroy will never be vetoed. Default:
0 .
TEXTSW_INSERT_FROM_FILE
string inserts the contents of a file into
a text subwindow at the current insertion point.
TEXTSW_INSERT_MAKES_VISIBLE
Textsw_enum Controls whether insertion causes repositioning to make
inserted text visible. Possible values are TEXTSW_ALWAY S,
TEXTSW_NEVER and TEXTSW_IF_AUTO_SCROLL.
Default: TEXTSW_IF_AUTO_SCROLL.
TEXTSW_INSERTION_POINT
Textsw_index Index of the current insertion point. Get, set.
TEXTSW_LEFT_MARGIN
int Number of pixels in the margin on left. Default: 4. Create, get.
TEXTSW_LENGTH
int Length of the textsw’s contents. Get only.
TEXT SW_LINE_BREAK_ACTION
Textsw_enum Determines how the textsw treats file lines too big
to fit on one display line. Possible values are either
TEXTSW_CLIP or TEXTSW_WRAP_AT_CHAR.
Default: TEXTSW_WRAP_AT_CHAR. Create, set.
TEXTSW_LOWER_CONTEXT
int Minimum # of lines to maintain between insertion point
and the bottom of view. Used by auto scrolling when type-in
would disappear off bottom of view.
-1 means defeat auto scrolling. Default: 2.
Xr microsystems
Revision A, of May 9,1988
368 SunView 1 Programmer’s Guide
Table 19-27
Text Subwindow Attributes — Continued
Attribute
Value Type
Description
TEXTSW_MEMORY_MAXIMUM
int
How much memory to use when not editing files. This attribute only
takes effect at textsw window creation time or after the window has
been reset via textsw_reset(). The lower bound of the attribute is 1000
bytes which is silently enforced. Default: 20,000 bytes. (If a great
deal of text will be inserted into the text subwindow, either by the pro¬
gram or the user, you may need to increase this.)
TEXTSW_MENU
Menu
The text subwindow’s menu. Get, set.
TEXTSW_MODIFIED
boolean
Whether or not the textsw has been modified. Get only.
TEXTSW_MULTI_CLICK_SPACE
int
Max # of pixels that can be between successive mouse clicks
and still have the clicks be considered a multi-click. Default: 3.
TEXTSW_MOLTI_CLICK_TIMEOUT
int
Max # of milliseconds that can be between successive
mouse clicks and still have the clicks be considered
a multi-click. Default: 390.
TEXTSW_NOTIFY__PROC
(procedure)
Notify procedure. Form is:
void
not if y_j?roc (textsw, avlist)
Textsw textsw
Attr_avlist avlist
Default: NULL, meaning standard procedure.
TEXTSW__READ_ONLY
boolean
When TRUE, prevents editing of the displayed text. If another file
is loaded in, READ_ONLY is turned off again. Default: FALSE.
TEXTSW_SCROLLBAR
Scrollbar
Scrollbar to use for text subwindow scrolling.
NULL means no scrollbar.
Default: A scrollbar with default attributes.
Note: text subwindow has a scrollbar by default, so you would
only use this to get no scrollbar, or to get the scrollbar handle.
TEXTSW_STATUS
Textsw_status *
If set, specifies the address of a variable of type
Textsw status into which a value is written that reflects
what happened during the call to window_create().
(For possible values, see the Textsw_status Values table).
TEXT SW_STORE_CHANGE S_F ILE
boolean
If TRUE, Store changes the file being edited to that named
as the target of the Store. If FALSE, Store does not affect
which file is being edited. Default: TRUE.
TEXTSW_STORE_SELF_I S_SAVE
boolean
Causes textsw to interpret a Store to the name of the current file
as a Save. Default: FALSE. Create, get.
microsystems
Revision A, of May 9,1988
Chapter 19 — SunView Interface Summary (Text Subwindow Attributes) 369
Table 19-27
Text Subwindow Attributes — Continued
Attribute
Value Type
Description
TEXTSW__UP DATE__SCROLLBAR
(no value)
Causes text subwindow to update the bubble in the scrollbar.
Set only — get returns NULL.
TEXTSW_UPPER_CONTEXT
int
Min # of lines to maintain between the start of the selection and
top of view. -1 means to defeat the normal actions. Default: 2.
microsystems
Revision A, of May 9, 1988
370 SunView 1 Programmer’s Guide
Table 19-28 Textsw_
action Attributes
Attribute
Value Type
Description
TEXT SW_ACTION_CAPS_LOCK
boolean
The user pressed the CAPS-lock function key to change the
setting of the CAPS-lock (it is initially 0, meaning off).
TEXTSW_ACTION_CHANGED_DIRECTORY
char *
The current working directory for the process has been
changed to the directory named by the provided string value.
TEXTSW_ACTIONJEDITED_FILE
char *
The file named by the provided string value has been edited.
Appears once per session of edits (see below).
TEXTSW_ACTION_EDITED_MEMORY
none
monitors whether an empty text subwindow has been edited.
TEXTSW_ACTION_FILE_IS_READONLY
char *
The file named by the provided string value does not have
write permission.
TEXTSW_ACTION_LOADED_FILE
char *
The text subwindow is being used to view the file named
by the provided string value.
TEXTSW_ACTION_TOOL_CLOSE
(no value)
The frame containing the text subwindow should become
iconic.
TEXTSW_ACTION_TOOL_DESTROY
Event *
The tool containing the text subwindow should exit,
without checking for a veto from other subwindows.
The value is the user action that caused the destroy.
TEXTSW_ACTION_TOOL_QOIT
Event *
The tool containing the text subwindow should exit
normally. The value is the user action that caused
the exit.
TEXT SW_ACTION_TOOL_MGR
Event *
The tool containing the text subwindow should do the
window manager operation associated with the
provided event value.
TEXT SW_ACTION_USING_MEMORY
(no value)
The text subwindow is being used to edit a string stored in
primary memory, not a file.
Revision A, of May 9, 1988
Chapter 19 — SunView Interface Summary (Textsw status Values) 371
Table 19-29 Textsw status Values
Value
Description
TEXTSW_STATUS_OKAY
The operation encountered no problems.
TEX T SW_S TAT U S_BAD_AT TR
The attribute list contained an illegal or unrecognized attribute.
TEXT SW_S TATU S_BAD_AT TR_VALUE
The attribute list contained an illegal value for an attribute,
usually an out of range value for an enumeration.
TEXTSW_STATUS_CANNOT_ALLOCATE
A call to calloc(2) or malloc(2) failed.
TEXTSW STATUS_CANNOT_OPEN_INPUT
The specified input file does not exist or cannot be accessed.
TEXTSW STATUS_CANNOT_INSERT_FROM_FILE The operation encountered a problem when trying
to insert from file.
TEXTSW_STATUS_OUT_OF_MEMORY
The operation ran out of memory while editing in memory.
TEXTSW_STATUS_OTHER_ERROR
The operation encountered a problem not covered by any of
the other error indications.
Asun
\r microsystems
Revision A, of May 9,1988
372 SunView 1 Programmer’s Guide
Table 19-30 Text Subwindow Functions
Definition
Description
Textsw_mark
textsw_add_mark(textsw, position, flags)
Textsw textsw;
Textsw__index position;
unsigned flags;
Adds a new mark at position.
flags can be either TEXTSW_MARK_DEFAULTS or
TEXT SW_MARK_MOVE_AT_INSERT.
int
textsw append__file__name (textsw, name)
Textsw textsw;
char *name;
Returns 0 if textsw is editing a file,
and if so appends the name of the file at the end of name.
Textsw__index
textsw_delete(textsw, first, last_plus_one)
Returns 0 if the operation fails.
Removes the span of characters beginning with first,
Textsw textsw;
Textsw__index first, last_plus__one;
and ending one before last_plus__one.
Textsw_index
textsw_edit(textsw, unit, count, direction)
Textsw textsw;
unsigned unit, count, direction;
Returns 0 if the operation fails. Erases a character, word or
line, depending on whether unit is SELN_LEVEL_FIRST,
SELN_LEVEL_FIRST+l, or SELN_LEVEL_LINE. If
direction is 0, characters after the insertion point are
affected, otherwise characters before the insertion point are
affected. The operation will be done count times.
Textsw_index
textsw_erase(textsw, first, last_plus_one)
Textsw textsw;
Textsw_index first, last_plus_one;
Returns 0 if the operation fails.
Equivalent to text sw__delete () ,but does not
affect the global shelf.
void
textsw_f ile_lines__visible (textsw, top, bottom)
Textsw textsw;
int *top, *bottom;
Fills in top and bottom with the file line indices of
the first and last file lines being displayed in textsw.
int
textsw_find_bytes(textsw, first, last_plus_one,
buf, buf_len, flags)
Textsw textsw;
Textsw index *first, *last j>lus_one;
char *buf;
unsigned buf_len, flags;
Beginning at the position addressed by first, searches for the
pattern specified by buf of length buf_len. Searches
forwards if flags is 0, else searches backwards.
Returns -1 if no match, else matching span placed in
indices addressed by first and last_plus_one.
Asun
Xr microsystems
Revision A, of May 9, 1988
Chapter 19 — SunView Interface Summary (Text Subwindow Functions) 373
Table 19-30 Text Subwindow Functions — Continued
Definition
Description
Textsw index
textsw_find_mark(textsw, mark)
Textsw textsw;
Textsw_mark mark;
Returns the current position of mark. If
this operation fails, it will return TEXTS W_INFINITY.
Textsw
textsw_first(textsw)
Textsw textsw;
Returns the first view into textsw.
Textsw_index
textsw_index_for_file_line(textsw, line)
Textsw textsw;
int line;
Returns the character index for the first
character in the line given by line. If this operation
fails, it will return TEXTSW_CANNOT_SET.
Textsw_index
textsw_insert(textsw, buf, buf len)
Textsw textsw;
char *buf;
int buf_len;
Inserts characters in buf into textsw
at the current insertion point.
The number of characters actually inserted
is returned — this will equal buf_len
unless there was a memory allocation failure.
If there was a failure, it will return 0.
textsw_match_bytes(textsw, first, last_plus one,
start_sym, start_sym_len,
Searches for a block of text in the textsw’s contents
which starts with characters matching start_sym and
end_sym, end_sym_len, field_flag) ends with characters matching end_sym.
Textsw textsw;
Textsw_index *first, *last_plus_one;
char *start_sym, *end_sym;
int start_sym_len, end_sym_len;
unsigned field_flag;
This function places the starting index of the matching block in
first and its ending index in last.
Textsw
textsw_next(textsw)
Textsw textsw;
Returns the next view in the set of views into text sw.
void
textsw_normalize_view(textsw, position)
Textsw textsw;
Textsw_index position;
Repositions the text so that the character
at position is visible and at the top of the subwindow.
void
textsw_possibly_normalize(textsw, position)
Textsw textsw;
Textsw__index position;
If the character at position is already visible, this function
does nothing. If it is not visible, it repositions the text
so that it is visible and at the top of the subwindow.
Asun
Xr microsystems
Revision A, of May 9, 1988
374 SunView 1 Programmer’s Guide
Table 19-30 Text Subwindow Functions — Continued
Definition
Description
void
textsw remove_mark(textsw, mark)
Textsw textsw;
Textsw_mark mark;
Removes an existing mark from textsw.
Textsw_index
textsw replace_bytes(textsw, first,
la st_plu s_one,
buf, buf__len)
Textsw textsw;
Textsw_index first;
char *buf;
unsigned buf___len;
Replaces the character span from first to
last_plus_one by the characters in buf.
last plus one. The return value is the net
number of bytes inserted. The number is negative if the
original string is longer than the one that replaces it If
this operation fails, it will return a value of 0.
void
textsw_reset(textsw, x, y)
Textsw textsw;
int x, y;
Discards edits performed on the contents of textsw.
If needed, a message box will be displayed at x, y.
unsigned
textsw_save(textsw, x, y)
Textsw textsw;
int x, y;
Saves any edits made to the file currently
loaded into textswJf needed, a message box
will be displayed at x, y.
int
textsw screen_line_count (textsw)
Textsw textsw;
Returns the number of screen lines in textsw.
void
textsw scroll_lines(textsw, count)
Textsw textsw;
int count;
Moves the text up or down by count lines. If count
is positive, then the text is scrolled up on the screen,
(forward in the file); if negative, the text is scrolled down,
(backward in the file).
void
textsw_set_selection(textsw, first, last_plus_one,
type)
Textsw textsw;
Textsw index first, last_plus_one;
unsigned type;
Sets the selection to begin at first and include all
characters up to last_plus_one.
#sun
XT microsystems
Revision A, of May 9,1988
Chapter 19 — SunView Interface Summary (Text Subwindow Functions) 375
Table 19-30 Text Subwindow Functions — Continued
Definition
Description
unsigned
textsw_store_file(textsw, filename, x, y)
Stores the contents of textsw
Textsw textsw;
to the file named by filename. If needed, a
char *filename;
message box will be displayed at x, y.
int x, y;
Revision A, of May 9, 1988
376 Sun View 1 Programmer's Guide
Table 19-31 TTY Subwindow Attributes
Attribute
.
Type
. ...
Description
TTY_ARGV
char **
Argument vector: name of the pro¬
gram running in the tty subwindow,
followed by arguments for that pro¬
gram.
TTY_CONSOLE
boolean
If TRUE, tty subwindow is con¬
sole. Set only. Default: FALSE.
TTY_PAGE_MODE
boolean
If TRUE, output will stop after
each page. Default: FALSE.
TTY_QU I T_ON_CH I LD_DEATH
boolean
If TRUE, window_done () is
called on the subwindow when its
child terminates. Set only. Default:
FALSE.
Table 19-32 TTY Subwindow Functions
Definition
Description
int
ttysw_input(tty, buf, len)
Tty tty;
char *buf;
Appends len number of characters from buf
onto tty’s input queue. It returns the number
of characters accepted.
int len;
int
ttysw_output(tty, buf, len)
Tty tty;
char *buf;
int len;
Appends len number of characters from buf
onto tty’s output queue, i.e. they are sent
through the terminal emulator to the TTY. It
returns the number of characters accepted.
microsystems
Revision A, of May 9, 1988
Chapter 19 — SunView Interface Summary (TTY Subwindow Special Escape Sequences) 377
Table 19-33 TTY Subwindow Special Escape Sequences
' _ _
Escape Sequence 103
Description
\E [It
open frame.
\E[2t
close frame.
\E[3t
move frame with interactive feedback.
\E[3;TOP;LEFTt
move frame to location specified by (TOP,LEFT).
\E[4t
resize frame with interactive feedback.
\E[4;WIDTH;HEIGHTt
resize frame to WIDTH and HEIGHT.
\E[5t
expose.
\E[6t
hide.
\E[7t
redisplay.
\E[8;ROWS;COLSt
resize frame so its width and height are ROWS and COLS.
\E[lit
report if frame is open or closed by sending \ [ It or \ [2t, respectively.
\E[13t
report frame’s position by sending the \E [ 3; TOP;LEFT t sequence.
\E[14t
report frame’s size in pixels by sending the \E [ 3 ; WIDTH; HEIGHT t sequence.
\E [ 18t
report frame’s size in characters by sending the \E [ 8 ;ROWS; COLS t sequence.
\E[20t
report the frame icon’s label by sending the \E [Llabel\E\ sequence.
\E[21t
report frame’s label by sending the \E] llabel\E\ sequence.
\E] ltext\E\
set frame’s label to text.
\E]Ifile\E\
set frame’s icon to the icon contained in file.
\E]Llabel\E\
set icon’s label to label.
\E [>OPTl; . . .OPTrih
turn requested options on. The only currently defined option is 1, for TTY_PAGE_MODE.
\E [>OPTl; . .OPTnk
turn requested options off.
Revision A, of May 9, 1988
378 SunView 1 Programmer’s Guide
Table 19-33
TTY Subwindow Special Escape Sequences — Continued
Escape Sequence 103
Description
\E [>OPTl; . . .OPTnl
report current option settings by sending \E [>OPTxl or \E>OPTh for each option*.
103 In this table “\E” denotes the <ESC> character, as it does in termcap.
®sun
Xr microsystems
Revision A, of May 9, 1988
Chapter 19 — SunView Interface Summary (Window Attributes) 379
Table 19-34
Window Attributes
Attribute
Value Type
Description
WIN_BELOW
Window
Causes the window to be laid out below window given as the value.
WIN_BOTTOM_MARGIN
int
Margin at bottom of window.
WIN_CLIENT_DATA
caddr_t
Client’s private data — for your use.
WIN_COLUMNS
int
Window’s width (including left and right margins) in columns.
WIN_COLUMN_GAP
int
Gap between columns in the window.
WIN_COLUMN_WIDTH
int
Width of a column in the window.
WI N__C ON S UME_KBD_E VENT
short
Window will receive this event.
WIN_CONSUME_KBD_EVENTS
list of short
Null terminated list of events window will receive. Create, set.
WIN_CONSUME_PICK_EVENT
short
Window will receive this pick event.
WIN_CONSUME_PICK_EVENTS
list of short
Null terminated list of pick events window will receive. Create, set.
WIN_CURSOR
Cursor
The window’s cursor. Note: the pointer returned by
window_get () points to per-process static storage.
WINJDEVICE_NAME
char *
UNIX device name associated with window, consisting of a string and
numeric part, e.g. win 10. Get only.
WIN_DEVICE_NUMBER
int
Numeric component of device name. Get only.
WIN_ERROR_MSG
char *
Error message to print before exit(l). Create only.
WI N_E VEN T_P ROC
(procedure)
Client’s callback procedure which receives input events:
Notify_value
event__proc (window, event, arg)
Window window;
Event *event;
caddr_t arg;
WI N_EVENT_ST ATE
short
Gets the state of the specified event code. For buttons and keys,
zero means “up,” non-zero means “down.” Get only.
WIN_FD
int
The UNIX file descriptor for the window. Get only.
WIN_FIT_HEIGHT
int
Causes window to fit its contents in the height dimension,
leaving a margin specified by the value given.
XT microsystems
Revision A, of May 9, 1988
380 SunView 1 Programmer’s Guide
Table 19-34
Window Attributes-
— Continued
Attribute
Value Type
Description
WIN_FIT_WIDTH
int
Causes window to fit its contents in the width dimension,
leaving a margin specified by the value given.
WIN_FONT
Pixfont *
The window’s font. Notes for the current release:
tty subwindows don’t use WIN_FONT. Frames don’t use WIN_FONT
to render their labels; however, they do use WIN_FONT
in calculating WIN_COLUMNS and WIN_ROWS. Setting WIN_FONT
does not cause the default system font to be set.
WI N_GRAB_ALL_INPUT
boolean
Window will get all events regardless of location.
WIN_HEIGHT
int
Window’s height in pixels. Value of WIN_EXTEND_TO_EDGE
causes subwindow to extend to bottom edge of frame.
Default: WI N_EXTEND_T0_EDGE.
WIN_HORIZONTAL_SCROLLBAR
Scrollbar
Horizontal scrollbar.
WI N_I GNORE_KBD_EVENT
short
Window will not receive this event.
WI N_I GNORE_KBD_EVENT S
list of short
Null terminated list of events window will not receive. Create, set.
WI N_I GNORE_P I CK_EVENT
short
Window will not receive this pick event.
WI N_I GNOREJ? I CK_EVENTS
list of short
Null terminated list of pick events window will not receive. Create, set.
WIN_INPUT_DESIGNEE
int
Window which gets events this window doesn’t consume. (Note that
the value must be the WIN_DEVICE_NUMBER of the designee).
WIN_KBD_FOCUS
boolean
Whether or not the window has the keyboard focus.
WIN_KBD_INPUT_MASK
Inputmask *
Window’s keyboard inputmask. Note: the pointer returned by
window_get () points to per-process static storage.
WI N_LEFT_MARGI N
int
Margin at left of window.
WIN_MENU
Menu
Window’s menu. Note: In the current release this doesn’t work for
panels or tty subwindows.
WI N_MOUSE_XY
int, int
Mouse’s position within the window. Set only.
WIN_NAME
char *
Name of window (currently unused by SunView).
WIN_OWNER
Window
Owner of window. Get only.
WIN_PERCENT_HEIGHT
int
Sets a subwindow’s height as a percentage of the frame’s height.
Revision A, of May 9, 1988
Chapter 19 — SunView Interface Summary (Window Attributes) 381
Table 19-34 Window Attributes — Continued
Attribute
Value Type
Description
WIN_PERCENT_WIDTH
int
Sets a subwindow’s width as a percentage of the frame’s width.
WIN_PICK_INPUT_MASK
Inputmask *
Window’s pick inputmask. Note: the pointer returned by
window_get () points to per-process static storage.
WIN_PIXWIN
Pixwin *
The window’s pixwin. Get only.
WIN_RECT
Rect*
Rect of the window. For frames, same as FRAME_OPEN_RECT.
Note: the pointer returned by window_get () for this attribute
points to per-process static storage.
WIN_RIGHT_MARGIN
int
Margin at right of window.
WIN_RIGHT_OF
Window
Causes the window to be laid out just to the
right of the window given as the value.
WIN_ROW_GAP
int
Gap between rows in the window.
WIN_ROW_HEIGHT
int
Height of a row in the window.
WIN_ROWS
int
Window’s height (including top and bottom margins) in rows.
WIN_SCREEN_RECT
Rect*
Rect of the screen containing the window. Get only.
Note: the pointer returned by window_get () for this attribute
points to per-process static storage.
WIN_SHOW
boolean
Causes the window to be displayed or undisplayed.
WI N_T OP_MARG IN
int
Margin at top of window.
WIN_TYPE
Window_type
Type of window. One of FRAME_TYPE, PANELJTYPE,
CANVASJTYPE, TEXTSWJTYPE or TTY_TYPE. Get only.
WIN_VERTICAL_SCROLLBAR
Scrollbar
Vertical scrollbar.
WIN_WIDTH
int
Window’s width in pixels. Value of WIN_EXTEND_TO_EDGE
causes subwindow to extend to right edge of frame.
Default: WIN_EXTEND_T0_EDGE.
WIN_X
int
x position of window, relative to owner.
WIN_Y
int
y position of window, relative to owner.
V microsystems
Revision A, of May 9, 1988
382 SunView 1 Programmer’s Guide
Table 19-35
Frame Attributes
Attribute
Value Type
Description
FRAME_ARGS
int, char **
Interpret command line arguments. Strips -W command-line frame
arguments out of argv. Create only.
FRAME_ARGC_PTR_ARGV
int *, char **
Interpret command line args. Strips -W command-line frame argu¬
ments out of argv, and decrements argc accordingly. Create only.
FRAME_BACKGROUND_COLOR
struct singlecolor *
Background color.
FRAME_CLOSED
boolean
Whether frame is currently closed.
FRAME_CLOSED_RECT
Rect *
Frame’s rect when closed.
FRAME_CMDL I NE_HELP_P ROC
(procedure)
Called when user types the command-line argument -WH. Default:
frame cmdline__help (program_name)
char *program_name;
FRAME_CURRENT_RECT
Rect *
Returns either FRAME_OPEN_RECT or FRAME_CLOSED_RECT,
depending on the value of FRAME__CLOSED.
Note: in the current release, there is a bug in the behavior
of FRAME CURRENT_RECT for subframes. It is set relative
to the owner frame, but it is retrieved relative to the screen.
FRAME_DEFAULT_D ONE_P ROC
(procedure)
Default value of FRAME_DONE JPROC. Get only.
The default procedure is to set the subframe to WIN_SHOW, FALSE.
FRAME_DONE_P ROC
(procedure)
Client’s proc called when user chooses ‘Done’ from subframe’s menu:
done_proc(frame)
Frame frame;
FRAME_EMBOLDEN_LABEL
boolean
If TRUE, frame’s label is rendered in bold.
FRAME_FOREGROUND_COLOR
struct singlecolor *
Foreground color.
FRAME_ICON
Icon
The frame’s icon.
FRAME_INHERIT__COLORS
boolean
If TRUE, colormap of frame is inherited by subwindows.
FRAME_LABEL
char *
The frame’s label.
FRAME_NO_CONFIRM
boolean
Set to TRUE before destroying a frame
to defeat confirmation. Set only.
FRAME_NTH_SUBFRAME
int
Returns frame’s nth (from 0) subframe. Get only.
Revision A, of May 9,1988
Chapter 19 — SunView Interface Summary (Frame Attributes) 383
Table 19-35
Frame Attributes — Continued
Attribute
Value Type
Description
FRAME_NTH_SUBWI NDOW
int
Returns frame’s nth (from 0) subwindow. Get only.
FRAME_NTH_WINDOW
int
Returns frame’s nth (from 0) window, regardless of whether
the window is a frame or a subwindow. Get only.
FRAME_OPEN_RECT
Rect *
Frame’s rect when open.
FRAME__SHOW__LABEL
boolean
Whether the label is shown. Default:
TRUE for base frames, FALSE for subframes.
FRAME_SUBWINDOWS_ADJUSTABLE
boolean
User can move sub window boundaries. Default: TRUE.
Xr microsystems
Revision A, of May 9, 1988
384 SunView 1 Programmer’s Guide
Table 19-36 Window Functions and Macros
:• ................................................................... .................................
I........................
Definition
Description
void
Queries the user defaults database
window_bell(win)
Window win;
to see if the user wants the bell to be
sounded, the window to be flashed, or both.
Window
window create(owner, type, attributes)
Window owner;
Kwindow type> type;
<attribute-list> att ribute s;
Creates a window and returns its handle,
type is one of FRAME, PANEL
TEXTSW, TTY, or CANVAS.
void
window default__event_j?roc (window, event, arg)
Window window;
Event *event;
caddr t arg;
Calls the default event procedure.
The arguments passed in are the window (canvas or panel),
the event, and an optional argument pertaining to the event.
window_destroy (win)
Window win;
Destroys win, and any sub windows or
subframes owned by win.
window done(win)
Window win;
Destroys the entire hierarchy to which win belongs.
window_fit(win)
Window win;
Causes win to fit its contents
in both dimensions. A macro, defined as:
window__set (win, WINJFIT, 0, 0).
window fit_height(win)
Window win;
Causes win to fit its contents
in the vertical dimension. A macro, defined as:
window_set (win, WIN_FIT_HEIGHT, 0, 0).
window fit width(win)
Window win;
Causes win to fit its contents
in the horizontal dimension. A macro, defined as:
window_set(win, WIN_FIT_WIDTH, 0, 0).
caddr_t
window_get(win, attribute)
Window win;
Window attribute attribute;
Retrieves the value of an attribute for win.
Asun
Xr microsystems
Revision A, of May 9,1988
Chapter 19 — SunView Interface Summary (Window Functions and Macros) 385
Table 19-36 Window Functions and Macros — Continued
Definition
Description
caddr__t
window_loop(subframe)
Frame subframe;
Causes subframe to be displayed, and receive all
input. The call will not return until window__return ()
is called from one of the application’s notify procs.
void
window_main__loop (base_f rame)
Frame base_frame;
Displays base_f rame on the screen and begins the
processing of events by passing control to the Notifier.
int
window_read_event(window, event)
Window window;
Event *event;
Reads the next input event for window.
In case of error, sets the global variable errno
and returns -1.
void
window_refuse_kbd_focus (window)
Window window;
When your event handler receives a KBD_REQUEST
event, call this function if you do not want your
window to become the keyboard focus.
void
window_release_event_lock (window)
Window window;
Releases the event lock, allowing other processes to receive input.
void
window_return(value)
caddr_t value;
Usually called from one of the application’s panel item
notify procs. Causes window_loop () to return.
window set (win, attributes)
Window win;
<attribute-list> attributes;
Sets the value of one or more of win’s attributes.
attributes is a null-terminated attribute list.
Asun
Xr microsystems
Revision A, of May 9,1988
386 SunView 1 Programmer’s Guide
Table 19-37 Command Line Frame Arguments
Flag
Long Flag
Arguments
Corresponding Attributes
-Wb
-background_color
red green blue
FRAME_BACKGROUND_COLOR
-Wh
-height
lines
WIN_ROWS
-WH
-help
—
(Causes FRAME_CMDLINE_HELP_PROC to be called.)
-Wf
-foreground color
red green blue
FRAME_FOREGROUND_COLOR
-Wg
. -set__default_color
—
FRAME_INHERIT_COLORS, TRUE
-Wi
-iconic
—
FRAME_CLOSED, TRUE
-WI
-icon__image
filename
ICON__IMAGE of frame’s icon 105
-WI
-label
label
FRAME_LABE L
-WL
-icon_label
label
ICON_LABEL of frame’s icon
-Wn
-no_JLabel
—
FRAME_SHOW_LABEL, FALSE
-Wp
-position
xy
WIN_X, WIN_Y
-WP
-icon__position
xy
FRAME_CLOSED_RECT
-Ws
-size
xy
WIN__WIDTH, WIN_HEIGHT
-Wt
-font
filename
(Sets system default font)
-WT
-icon__font
filename
ICON_FONT of frame’s icon
-Ww
-width
columns
WIN_COLUMNS
105 The -WI option will not work if the application’s code does not already specify its icon.
microsystems
Revision A, of May 9, 1988
Example Programs
Example Programs . 389
Source Available. 389
A.l .filer . 389
A.2. image browser_1 . 401
A.3. image_browser_2 . 406
A.4. tty jo . 412
A.5. fontjnenu . 416
A.6. resize_demo . 425
A.7. detool . 430
A. 8 . typein . 437
A.9. Programs that Manipulate Color. 441
color edit . 441
animatecolor . 447
A. 10. Two gfx subwindow-based programs converted to use
SunView. 454
bounce . 454
spheres .. 461
Source Available
A.l. filer
A
Example Programs
If the appropriate optional software category has been installed or mounted on
your system, the source code for some of these examples programs is available
on-line in /usr/share/src/sun/suntool/examples. In addition, the
directory above this (/usr/share/src/sun/suntool) contains the source
for many of the SunView 1 programs in the SunOS, such as textedit,
perfmeter, and iconedit.
This program is discussed in Chapter 4, Using Windows. It displays a listing in a
tty subwindow, which the user manipulates through panel items.
If the user presses the [ Prons I key in the panel, or chooses ‘Props’ from the frame
menu, or pushes the Set Is flags button, a pop-up subframe appears, filer uses the
Selection Service to determine what file name the user has selected, and creates a
pop-up text subwindow where that file is displayed.
filer uses the alerts package to ask the user for confirmation and put up messages.
It also includes old code which mimics alerts by using window_loop () to put
up a subframe, but programs written for SunOS Release 4.0 and beyond in gen¬
eral will have no need for this.
microsystems
389
Revision A, of May 9, 1988
390 SunView 1 Programmer’s Guide
/*****************************************************************************/
/* 4.0 filer.c */
/*****************************************************************************/
#include <suntool/sunview.h>
#include <suntool/panel.h>
#include <suntool/tty.h>
#include <suntool/textsw.h>
#include <suntool/seln.h>
#include <suntool/alert.h>
#include <sys/stat.h> /* stat call needed to verify existence of files */
/* these objects are global so their attributes can be modified or retrieved */
Frame base_frame, edit_frame, ls_flags_frame;
Panel panel, ls_flags__panel;
Tty ttysw;
Textsw editsw;
Panel_item dir_item, fname_item, filing_mode_item, done_item;
int quit_conf irmed_from_j?anel;
#define
#define
MAX_FILENAME_LEN
MAX PATH LEN
256
1024
char *getwd();
main (argc, argv)
int argc;
char **argv;
{
static Notify_value filer_destroy_func();
void ls_flags_proc () ;
base_frame = window__create (NULL, FRAME,
FRAME_ARGS, argc, argv,
FRAME_LABEL, "filer”,
FRAME_PROP S_ACT 10N_PR0C, 1 s_f lags_j?roc,
FRAME_PROPS_ACTIVE, TRUE,
FRAME_N0_C0NFIRM, TRUE,
0 );
(void) notify_interpose_destroy_func (base_frame, filer_destroy__func) ;
create_panel_subwindow () ;
create__tty_subwindow () ;
create_edit_popup () ;
create_ls_f lags_popup () ;
quit__conf irmed_f rom_j>anel = 0;
window_main__loop (base_frame) ;
exit (0);
}
create__tty_subwindow ()
{
ttysw = win do w__c reate (base_frame, TTY, 0) ;
}
create_edit_popup ()
{
m sun
Nr microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs (filer ) 391
r
edit__frame = window_create (base
_frame, FRAME,
FRAME SHOW LABEL,
TRUE,
0);
}
editsw = window__create (edit_f rame, TEXTSW, 0);
ere
{
ate_j?anel_subwindow ()
void ls_proc() , ls_flags_j?roc ()
, quit_proc(), edit_proc (),
edit_sel_proc(), del_proc()
/
char current_dir [MAX_PATH__LEN];
panel = window_create(base_frame, PANEL, 0);
(void) panel_create_item(panel,
PANEL_BUTTON,
PANEL LABEL_X,
ATTR_COL(0),
PANEL LABEL Y,
ATTR_ROW(0),
PANEL_LABE L_IMAGE,
panel_button_image(panel, "List Directory", 0, 0),
PANEL NOTIFY_PROC,
ls_proc.
0);
(void) panel_create__item (panel,
PANEL_BUTTON,
PANE L_L ABE L_I MAGE,
panel_button_image(panel, "Set Is flags", 0, 0),
PANEL NOTIFY_PROC,
ls_f lags_proc.
0);
(void) panel_create__item(panel.
PANEL_BUTTON,
PANE L_L ABE L_I MAGE,
panel_button_image(panel, "Edit", 0, 0),
PANEL NOTIFY PROC,
edit _p roc.
0);
(void) panel_create_itern (panel,
PANEL_BUTTON,
P ANEL_LABE L__I MAGE,
panel_button_image(panel, "Delete", 0, 0),
PANEL_N OTIFY_PROC,
del_proc.
0);
*
(void) panel_create_itern(panel.
PANEL_BUTTON,
PANEL_LABEL_IMAGE,
panel_button_image(panel, "Quit", 0, 0),
PANEL_NOTIFY_PROC, quit_proc.
0);
filing mode_item = panel__create
item(panel, PANEL_CYCLE,
PANE L_LABE L_X,
ATTR_C0L(0) ,
PANE L_LABE L_Y,
ATTR_ROW(1) ,
PANEL_LABEL_STRING,
"Filing Mode:",
PANEL_CHOICE_STRINGS,
"Use \"File:\" item",
t'Use Current Selection", 0,
0);
(void) panel_create_item(panel,
PANE L_ME S SAGE,
PANE L_LABE L__X,
ATTR_COL(0) ,
PANE L_LABE L_Y,
ATTR_ROW(2),
0);
dir item = panel_create_item(panel, PANEL_TEXT,
PANE L_LABE L_X,
ATTR_COL(0),
V_
PANE L_LABE L_Y,
ATTR_ROW (3),
_ t
sun Revision A, of May 9, 1988
microsystems
392 SunView 1 Programmer’s Guide
(—
PANEL VALUE DISPLAY_LENGTH,
60,
PANEL__VALUE,
getwd(current_dir),
PANEL_LABEL_STRING,
"Directory: ",
0);
fname__item = panel__create_item (panel, PANEL_TEXT,
PANE L_LABE L_X,
ATTR__C0L (0) ,
PANEL__LABEL_Y,
ATTR_R0W(4),
PANEL_LABEL_DISPLAY_LENGTH,
60,
PANEL LABEL STRING,
"File: ",
0);
window__fit_height (panel) ;
}
window_set (panel, PANEL__CARET_ITEM, fname_item, 0);
create_ls_flags_popup ()
/
void done_proc();
ls_flags_frame = window__create (base_frame, FRAME, 0);
ls_flags_panel = window__create (ls_
_flags_frame, PANEL, 0);
panel_create_item(ls_f lags_panel.
PANEL_MESSAGE,
PANEL_ITEM_X,
ATTR__C0L (14) ,
PANEL_ITEM_Y,
ATTR__R0W (0) ,
PANEL_LABEL_STRING,
"Options for Is command".
PANEL CLIENT DATA,
H ii
t
0);
panel__create_item(ls_flags_panel.
PANEL_CYCLE,
PANEL_ITEM_X,
ATTR_C0L(0) ,
PANEL_ITEM_Y,
ATTR_R0W(1),
PANEL_D I SPLAY_LEVEL,
PANEL_CURRENT,
PANEL_LABEL_STRING,
"Format:
ii
r
PANE L_CH01CE_STRINGS,
"Short", "Long", 0,
PANEL CLIENT_DATA,
i. 1 ",
o
pan e l_c r e a t e__i t em (1 s_f 1 a g s_j>a ne 1,
PANEL_CYCLE,
PANEL_ITEM_X,
ATTR__C0L (0) ,
PANEL_ITEM_Y,
ATTR_R0W(2),
PANE L_D ISP LA Y__LEVEL,
PANEL__CURRENT,
PANEL_LABEL_STRING,
"Sort Order:
ii
r
PANEL_CH0ICE_STRINGS,
"Descending", "Ascending", 0,
PANE L_CL I ENT_D ATA,
ii r ii
r
o
panel_create_item(ls_flags_panel.
PANE L_CY CLE,
P ANEL__I TEM_X,
ATTR_C0L(0) ,
PANEL__ITEM_Y,
ATTR_R0W(3),
PANEL_D I SPLAY_LEVEL,
PANEL_CURRENT,
PANEL_LABEL_STRING,
"Sort criterion:
ii
r
PANE L_CH01CE_STRINGS,
"Name", "Modification Time",
"Access Time", 0,
PANEL CLIENT DATA,
r+
d
0);
sun Revision A, of May 9, 1988
microsystems
Appendix A — Example Programs (filer ) 393
/
panel_create_item(ls_flags _j?anel.
PANE L_CY CLE,
PANEL_ITEM_X,
ATTR_C0L(0) ,
PANEL_ITEM_Y,
ATTR_R0W(4) ,
PANEL DISPLAY LEVEL,
PANEL CURRENT,
PANEL LABEL STRING,
"For directories, list: ",
PANEL_CHOICE_STRINGS ,
"Contents", "Name Only", 0,
PANE L_CL I ENT_D ATA,
" d ",
0);
panel_creat e_item (1 s_f lags_panel,
PANE L_CY CLE,
PANEL_ITEM_X,
ATTR_C0L(0) ,
P ANEL_I TEM_Y,
ATTR_R0W(5) ,
PANEL DISPLAY LEVEL,
PANEL CURRENT,
PANEL_LABEL_STRING,
"Recursively list subdirectories? ",
PANEL_CH0ICE_STRINGS,
"No", "Yes", 0,
PANEL CLIENT DATA,
" R ",
o
panel_create_item(ls_flags_panel.
PANE L_CY CLE,
PANEL_ITEM_X,
ATTR_C0L(0),
P ANEL_I TEM__Y,
ATTR_R0W(6),
PANEL DISPLAY LEVEL,
PANEL_CURRENT,
PANEL LABEL_STRING,
"List '. f files? ",
PANEL CHOICE STRINGS,
"No", "Yes", 0,
PANEL_CLIENT_DATA,
l» a II
a ,
o
panel_create_item(ls_flags _panel.
PANE L___CY CLE,
PANEL_ITEM_X,
ATTR__C0L (0) ,
PANEL_ITEM_Y,
ATTR__R0W (6) ,
PANEL_D ISP LA Y_LEVEL,
PANEL_CURRENT,
PANEL_LABEL__STRING,
"Indicate type of file? ",
PANEL_CHOICE_STRINGS,
"No", "Yes", 0,
P ANEL_CLI ENT_D ATA,
" F ",
o
done_item = panel_create_item(ls_
flags_panel, PANELJBUTTON,
PANEL_ITEM_X,
ATTR_COL(0),
PANEL_ITEM_Y,
ATTR_ROW(7),
PANEL__LABEL_IMAGE,
panel_button_image(panel, "Done", 0, 0),
PANEL NOTIFY__PR0C,
done_j?roc.
0);
window fit(ls_flags_panel); /* fit panel around its items */
}
window fit(ls_flags_frame); /* fit frame around its panel */
char *
compose_ls_options ()
/
static char flags[20];
char *ptr;
char flag;
int first__flag = TRUE;
Panel__item item;
char *client_data;
int index;
V_
ptr = flags;
sun Revision A, of May 9, 1988
microsystems
394 SunView 1 Programmer’s Guide
panel_each_item(ls_flags _j?anel, item)
if (item != done_item) {
client_data = panel_get(item, PANEL_CLIENT_DATA, 0);
index = (int)panel_get_value(item);
flag = client_data[index];
if (flag !=''){
if (first__flag) {
*ptr++ =
first_flag = FALSE;
}
*ptr++ * flag;
}
}
panel_end_each
*ptr = 'Non¬
return flags;
}
void
ls_proc ()
{ "
static char previous_dir [MAX_PATH_LEN] ;
char *current_dir;
char cmdstring[100]; /* dir_item's value can be 80, plus flags */
current_dir = (char *) panel__get_value (dir_item);
if (strcmp(current_dir, previous_dir)) {
chdir ( (char *)panel_get_value (dir_item)) ;
strcpy(previous_dir, current_dir);
}
sprintf(cmdstring, "Is %s %s/%s\n",
compose_ls_options(),
current_dir,
panel_get_value(fname_item));
ttysw_input(ttysw, cmdstring, strlen(cmdstring));
}
void
ls_f lags_jproc ()
{ "
window_set (ls_flags_frame, WIN_SHOW, TRUE, 0);
}
void
done_proc ()
{
window_set (ls_flags_f rame, WIN_SHOW, FALSE, 0);
}
/* return a pointer to the current selection */
char *
get_selection ()
{
static char filename[MAX_FILENAME_LEN];
Seln_holder holder;
Seln__request ^buffer;
m sun
\r microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs (filer ) 395
holder = seln_inquire(SELN_PRIMARY);
buffer = seln_ask(&holder, SELN_REQ_CONTENTS_ASCII, 0, 0);
strncpy(
filename, buffer->data + sizeof(Seln_attribute), MAX_FILENAME_LEN);
return(filename);
}
/* return 1 if file exists, else print error message and return 0 */
stat_file(filename)
char *filename;
{
static char previous_dir [MAX_PATH_LEN] ;
char *current_dir;
char this_file [MAX_PATH_LEN] ;
struct stat statbuf;
current_dir = (char *)panel_get_value(dir_item);
if (strcmp(current_dir, previous_dir)) {
chdir((char *)panel_get_value(dir_item));
strcpy(previous_dir, current_dir);
}
sprintf(this_file, "%s/%s", current_dir, filename);
if (stat(this_file, fcstatbuf) < 0) {
char buf[MAX_FILENAME_LEN+11]; /* big enough for message */
sprintf(buf , "%s not found.", this_file);
msg(buf, 1);
return 0;
}
return 1;
}
void
edit_proc ()
{
void edit_f ile_proc () , edit_sel_proc () ;
int file_mode = (int) panel_get__value (filing_mode_item) ;
if (file_mode) {
(void) edit_sel_proc () ;
} else {
(void) edit_f ilej>roc () ;
}
}
void
edit_f ile_proc ()
{
char *filename;
/* return if no selection */
if (!strlen(filename = (char *)panel_get_value(fname_item))) {
msg("Please enter a value for \"File:\".", 1);
return;
}
/* return if file not found */
if (!stat_file(filename))
m sun
\T microsystems
Revision A, of May 9, 1988
396 SunView 1 Programmer’s Guide
return;
window_set(editsw, TEXTSW_FILE, filename, 0);
window_set(edit_frame, FRAME_LABEL, filename, WIN_SH0W, TRUE, 0);
}
void
edit_sel_jproc ()
{
char *filename;
/* return if no selection */
if (!strlen(filename = get_selection ())) {
msg("Please select a file to edit.", 0);
return;
}
/* return if file not found */
if (!stat_file(filename))
return;
window_set(editsw, TEXTSW_FILE, filename, 0);
window_set(edit_frame, FRAME_LABEL, filename, WIN_SH0W, TRUE, 0);
}
void
del_proc()
{
char buf[300];
char *filename;
int result;
Event event; /* unused */
int file_mode = (int) panel_get_value (filing_mode_item) ;
/* return if no selection */
if (file_mode) {
if (!strlen(filename = get_selection())) {
msg("Please select a file to delete.", 1);
return;
}
} else {
if (!strlen(filename = (char *)panel_get_value(fname_item))) {
msg("Please enter a file name to delete.", 1);
return;
}
}
/* return if file not found */
if (!stat_file(filename))
return;
/* user must confirm the delete */
result = alert^prompt(base_frame, Sevent,
ALERT_ME S SAGE_S TRINGS,
"Ok to delete file:",
filename.
m sun
\r microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs (filer ) 397
0,
ALERT_BUTTON_YES, "Confirm, delete file",
ALERT_BUTTON_NO, "Cancel",
0 );
switch (result) {
case ALERT_YES:
unlink(filename);
sprintf(buf, "%s deleted.", filename);
msg(buf, 0);
break;
case ALERT_N0:
break;
case ALERT_FAILED: /* not likely to happen unless out of FDs */
sprintf(buf, "Ok to delete file %s?", filename);
result = confirm^yes(buf);
if (result) {
unlink(filename);
sprintf(buf, "%s deleted.", filename);
msg(buf, 1);
}
break;
}
}
int
confirm_quit()
{
int result;
Event event; /* unused */
char *msg = "Are you sure you want to Quit?";
result = alert_prompt(base_frame, Sevent,
ALERT__ME S S AGE_S TRINGS,
"Are you sure you want to Quit?",
0,
ALERT_BUTTON_YES, "Confirm",
ALERT_BUTT0N_N0, "Cancel",
0 );
switch (result) {
case ALERT_YES:
break;
case ALERT_N0:
return 0;
case ALERT_FAILED: /* not likely to happen unless out of FDs */
result = confirm_yes(msg);
if (!result) {
return 0;
}
break;
}
return 1;
}
static Notify__value
filer_destroy_func(client, status)
Notify_client client;
Destroy_status status;
{
m sun
microsystems
Revision A, of May 9,1988
398 SunView 1 Programmer’s Guide
if (status == DESTROY__CHECKING) {
if (quit_confirmed_from_panel) {
return(notify_next_destroy_func(client, status));
} else if (confirm_quit() == 0) {
(void) notify_veto_destroy((Notify_client)(LINT_CAST(client)));
return(NOTIFY_DONE);
}
}
return(notify_next_destroy_func(client, status));
}
void
quit_jproc ()
{
if (confirm_quit()) {
quit_confirmed_from_panel = 1;
window_destroy (base__frame) ;
}
}
msg(msg, beep)
char *msg;
int beep;
{
char buf[300];
int result;
Event event; /* unused */
char *contine_msg - "Press \"Continue\" to proceed.";
result = alert_prompt(base_frame, fcevent,
ALERT_MESSAGE__STRINGS,
msg,
contine_msg,
0,
ALERT_N0_BEEPING, (beep) ? 0:1,
ALERT_BUTTON_YES, "Continue",
ALERT_TRIGGER, ACTION_STOP, /* allow either YES or NO answer */
0 );
switch (result) {
case ALERT_YES:
case ALERT_TRIGGERED: /* result of ACTI0N__ST0P trigger */
break;
case ALERT_FAILED: /* not likely to happen unless out of FDs */
sprintf(buf, "%s Press \"Continue\" to proceed.", msg);
result = conf irm__ok (buf);
break;
}
}
/* confirmer routines to be used if alert fails for any reason */
static Frame init_confirmer();
static int confirm();
static void yes_no_ok ();
int
confirm__yes (message)
char *message;
m sun
Xr microsystems
Revision A, of May 9,1988
Appendix A — Example Programs (filer) 399
{
return confirm(message, FALSE);
}
int
confirm_ok(message)
char *message;
{
return confirm(message, TRUE);
}
static int
confirm (message, ok_only)
char ^message;
int ok_only;
{
Frame confirmer;
int answer;
/* create the confirmer */
confirmer = init_confirmer(message, ok_only);
/* make the user answer */
answer = (int) window_loop(confirmer);
/* destroy the confirmer */
window_set (confirmer, FRAME__N0_C0NFIRM, TRUE, 0);
window_destroy(confirmer);
return answer;
static Frame
init_confirmer(message, ok_only)
char ^message;
int ok_only;
{
Frame
Panel
Panel__item
int
Rect
struct pixrect
confirmer;
panel;
message_item;
left, top, width
*r;
*pr;
height;
confirmer = window_create(0, FRAME, FRAME_SHOW_LABEL, FALSE, 0);
panel = window_create(confirmer, PANEL, 0);
message_item = panel_create_item(panel, PANEL_MESSAGE,
PANEL_LABEL_STRING, message, 0);
if (ok_only) {
pr = panel_button__image (panel, "Continue", 8, 0) ;
width = pr->pr_width;
} else {
pr = panel_button_image(panel, "Cancel", 8, 0);
width - 2 * pr->pr_width + 10;
}
/* center the yes/no or ok buttons under the message */
r = (Rect *) panel_get (message__item, PANEL_ITEM_RECT);
left = (r->r_width - width) / 2;
if (left < 0)
m sun
\r microsystems
Revision A, of May 9, 1988
400 SunView 1 Programmer’s Guide
left = 0;
top = rect_bottom(r) + 5;
if (ok__only) {
panel_create_item (panel , PANEL_BUTTON f
P ANEL__ITEM_X, left, PANEL_ITEM_Y, top,
P ANEL_LABEL_IMAGE, pr,
PANEL_CLIENT_DATA, 1,
PANEL_NOTIFY_PROC, yes_no_ok,
0 );
} else {
panel_create_item (panel, PANEL_BUTTON,
PANEL_ITEM_X, left, PANEL_ITEM_Y, top,
PANEL_LABEL_IMAGE, pr,
P ANEL_CL I ENT_D AT A, 0,
P ANEL_NOTIFY__PROC, yes_no__ok,
0 );
panel__create_item (panel, PANEL__BUTTON,
PANEL_LABEL_IMAGE, panel_button_image (panel, "Confirm", 8, 0) ,
P ANEL_CL I ENT_DAT A, 1,
PANEL_NOTIFY__PROC, yes_no__ok,
0 );
}
window_fit (panel) ;
window_fit(confirmer);
/* center the confirmer frame on the screen */
r
width
height
left
top
if (left <
left =
if (top <
top =
: 0 )
• 0 ;
0 )
0 ;
(Rect *) window__get(confirmer, WIN_SCREEN_RECT);
(int) window_get(confirmer, WIN_WIDTH);
(int) window_get(confirmer, WIN_HEIGHT);
(r->r__width - width) / 2;
(r->r_height - height) / 2;
window set(confirmer, WIN X, left, WIN_Y, top, 0);
return confirmer;
}
static void
yes_no__ok (item, event)
Panel_item item;
Event *event;
{
window__return (panel_get (item, PANEL_CLIENT_DATA) ) ;
}
Revision A, of May 9,1988
Appendix A — Example Programs (image browser l ) 401
A.2. image_browser_1 The following program is discussed in Chapter 4, Using Windows. It lets the
user browse through icons and display them. It shows a more complex subwin¬
dow layout.
XT microsystems
Revision A, of May 9,1988
402 SunView 1 Programmer’s Guide
/***************************************************************************/
/* image_browser_l.c */
/***************************************************************************/
#include <suntool/sunview,h>
♦include <suntool/panel.h>
♦include <suntool/tty.h>
♦include <stdio.h>
♦include <suntool/icon_load.h>
♦include <suntool/seln.h>
Frame frame;
Panel control_panel, display_panel;
Tty tty;
Panel__item dir_item, fname__item, image_item;
ls^proc(), show_proc(), quit_proc();
char *get_selection ();
♦define MAX_PATH_LEN 1024
♦define MAX_FILENAME_LEN 256
main(argc f argv)
int argc;
char **argv;
{
frame = window_create(NULL, FRAME,
FRAME_ARGS, argc, argv,
FRAME_LABE L, "image_browser_l”,
0 );
init__tty ();
init__control_panel () ;
init_display_panel () ;
window_fit (frame) ;
window__main_loop (frame) ;
exit (0);
}
init_tty ()
{
tty = window_create(frame, TTY,
WIN__COLUMNS, 30,
WIN_ROWS, 20,
0 );
}
m sun
XT microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs ( image_browser_l ) 403
init_control_panel()
{
char *getwd();
char current dir[1024];
control_panel = window_create(frame, PANEL, 0);
dir item “= panel_create_item(control_panel, PANEL_TEXT,
_ PANEL_VALUE_DISPLAY_LENGTH, 13,
PANEL_LABEL_STRING, "Dir: ",
PANEL_VALUE, getwd(current_dir),
0 );
fname_item - panel_create_item(control_panel, PANEL_TEXT,
PANEL_ITEM_X, ATTR_C0L(0),
PANEL_ITEM_Y, ATTR_ROW(1),
PANEL_VALUE_DISPLAY_LENGTH, 13,
PANEL_LABEL_STRING, "File:",
0 );
panel_create_item(control_panel, PANEL_BUTTON,
PANEL_ITEM_X, ATTR_C0L(0) ,
PANEL_ITEM_Y, ATTR_ROW(2),
PANEL_LABEL_IMAGE, panel_button_image(control_panel,"List"
PANEL_NOTIFY_PROC, ls_proc,
0 );
0 , 0 ),
/
panel_create_item(control_panel, PANEL_BUTTON,
PANEL_LABEL_IMAGE, panel_button_image(control_panel,"Show”,0,0),
PANEL_NOTIFY_PROC, show_proc,
0 );
panel_create_item(control_panel, PANEL_BUTTON,
PANEL_LABEL_IMAGE, panel_button_image(control_panel,"Quit",0,0),
PANEL_N OTIFY_PR0C, quit_proc,
0 );
window_fit(control_panel);
}
m sun
XT microsystems
Revision A, of May 9,1988
404 SunView 1 Programmer’s Guide
ls_proc()
{ "
static char previous_dir[MAX_PATH_LEN];
char *current_dir;
char cmdstring[100];
current_dir = (char *) panel_get__value (dir_item) ;
if (strcmp(current_dir, previous_dir)) {
chdir(current_dir);
sprintf(cmdstring, "cd %s\n", current_dir) ;
ttysw_input(tty, cmdstring, strlen(cmdstring));
strcpy(previous_dir, current_dir);
}
sprintf(cmdstring, "Is -1 %s\n", panel_get_value (fname_item) ) ;
ttysw_input(tty, cmdstring, strlen(cmdstring));
}
quit_proc()
{
window_destroy(frame);
}
show_jproc ()
{
char *filename;
if (!strlen(filename = get_selection ()))
return;
load__image (filename) ;
}
load_image(filename)
char *filename;
{
Pixrect *image;
char error_msg [ IL_ERRORMSG_SIZE ] ;
if (image = icon_load_mpr(filename, error_msg)) {
panel_set(image_item,
PANE L_ITEM_X, ATTR_COL(5),
PANEL_I TEM__Y, ATTR_ROW (4) ,
PANEL_LABEL_IMAGE, image,
0 );
}
}
m sun
\r microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs (image browser 1) 405
init_display_panel ()
display_panel * window_create(frame, PANEL,
WIN__BELOW, control_panel,
WIN_RIGHT_OF, tty,
0 );
image_item = panel_create_item(display_panel, PANEL_MESSAGE, 0);
}
char *
get_selection ()
{
static char filename[MAX_FILENAME_LEN];
Seln_holder holder;
Seln_request *buffer;
holder = seln_inquire(SELN_PRIMARY);
buffer = seln_ask(^holder, SELNJREQ_CONTENTS_ASCII, 0, 0);
strncpy(filename, buffer->data + sizeof(Seln_attribute), MAX_FILENAME__LEN) ;
return (filename);
J
Revision A, of May 9,1988
406 SunView 1 Programmer’s Guide
A.3. image_browser_2 The following program is discussed in Chapter 4, Using Windows. It is a more
complex icon browser than the previous example It illustrate how you can use
row!column space to specify the size of a subwindow.
Revision A, of May 9, 1988
Appendix A — Example Programs (image browser 2) 407
/***************************************************************************/
♦ifndef lint
static char sccsid[] = M @(#)image_browser_2.c 1.3 86/09/15 Copyr 1986 Sun Micro";
#endif
/***************************************************************************/
♦include <suntool/sunview.h>
♦include <suntool/panel.h>
♦include <suntool/tty.h>
♦include <stdio.h>
♦include <suntool/icon_load.h>
♦include <suntool/seln.h>
♦include <suntool/expand_name.h>
♦include <suntool/scrollbar.h>
static char namebuf[100];
static int file_count, image_count;
static struct namelist *name_list;
♦define get_name(i) name_list->names[(i)]
Frame frame;
Panel control_panel, display_panel;
Tty tty;
Panel_item dir_item, fname_item, image__item;
show_jproc () , browsej)roc () , quit_proc () ;
Pixrect *get_image () ;
char *get_selection();
♦define MAX_PATH_LEN 1024
♦define MAX_FILENAME_LEN 256
main(argc f argv)
int argc;
char **argv;
{
frame = window_create(NULL, FRAME,
FRAME_ARGS, argc, argv,
FRAME_LABEL, "image_browser_2",
0 );
init__control_panel () ;
init_display_j>anel ();
window_set (control_panel,
WIN_WIDTH, window_get(display_panel, WIN_WIDTH, 0),
0 );
window_fit (frame) ;
window_main__loop (frame) ;
exit(0);
}
m sun
XT microsystems
Revision A, of May 9, 1988
408 SunView 1 Programmer’s Guide
init__control__panel ()
{
char current_dir [MAX_PATH__LEN] ;
control_panel = window_create(frame, PANEL, 0);
dir_item = panel__create_item(control__panel, PANEL_TEXT,
PANEL_LABEL__X, ATTR_COL (0) ,
PANEL_LABEL_Y, ATTR_ROW (0) ,
PANEL_VALUE_DISPLAY_LENGTH, 23,
PANEL__VALUE, getwd (current_dir) ,
PANEL_LABEL__STRING, "Dir: " ,
0);
(void) panel_create_item(control_panel, PANEL_BUTTON,
PANEL_LABEL_IMAGE, panel_button_image(control_panel,"Browse",0,0),
PANEL_NOTIFY_PROC, browse_proc,
0);
fname__item = panel_create_item (control_j?anel, PANEL_TEXT,
PANEL_LABEL_X, ATTR_COL (0) ,
PANEL_LABEL__Y, ATTR_ROW (1) ,
PANEL_VALUE_DI SPLAY_LENGTH, 23,
PANEL_LABE L_STRING, "File:",
0);
(void) panel__create__item (control_panel, PANEL_BUTTON,
PANEL_LABEL_IMAGE, panel_button_image (control_panel, "Quit", 6,0) ,
PANEL_NOTIFY_PROC, quit_proc,
0);
window_fit_height (control_panel);
window_set(control_panel, PANEL_CARET_ITEM, fname_item, 0);
m sun
Nr microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs {image browser 2) 409
browse^proc()
{
Panel_item olcMLtem;
register int i;
int len;
Pixrect *image;
int previous_image_count;
register int row, col;
set_directory();
match_files() ;
panel__each_item (display_panel, old__item)
pr_destroy ((Pixrect *) panel_get (old_item, PANEL_LABEL__IMAGE) ) ;
panel_f ree (old__item) ;
panel_end_each
previous__image__count = image_count;
for (row = 0 f image__count = 0; image__count < file_count; row++)
for (col = 0; col < 4 && image_count < file_count; col++) {
if (image = get_image(image_count)) {
panel_create_item (display_panel f PANEL__MESSAGE,
PANEL__ITEM_Y f ATTR_ROW (row) f
PANEL_ITEM_X f ATTR_C0L (col) ,
PANEL_LABEL_IMAGE, image, 0);
image_count++;
}
}
if (image_count <=* previous_image__count)
panel_update__scrolling_size (display_panel) ;
panel_paint(display_panel, PANEL_CLEAR);
free_namelist (name__list);
}
set_directory()
{
static char previous_dir[MAX_PATH_LEN];
char *current__dir;
current_dir = (char *) panel_get_value (dir_item) ;
if (strcmp(current_dir, previous_dir)) {
chdir(current_dir);
strcpy(previous_dir, current_dir);
}
Pixrect *
get_image(i)
int i;
{
char error_msg[IL_ERRORMSG_SIZE];
return (icon_load_mpr(get_name(i), error_msg));
}
m sun
XT microsystems
Revision A, of May 9, 1988
410 SunView 1 Programmer’s Guide
match_files ()
{
char *val;
val = (char *)panel_get_value(fname_item);
strcpy(namebuf, val);
name_list = expand_name(namebuf);
file_count = name_list->count;
quit_proc()
{
window_destroy(frame);
}
show_j?roc ()
{
char *filename;
if (!strlen(filename = get_selection ()))
return;
load_image(filename);
}
load_image(filename)
char *filename;
{
Pixrect *image;
char error_msg[IL_ERRORMSG_SIZE];
if (image = icon_load_mpr(filename, error_msg)) {
panel_set(image__item,
PANEL_ITEM_X, ATTR_COL(5) f
PANE L_ITEM_Y f ATTR_R0W(4) f
PANEL_LABEL_IMAGE, image,
0 );
}
}
m sun
\r microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs (image browser 2 ) 411
init_display_panel ()
{
int width;
Scrollbar sb = scrollbar_create(SCROLL__MARGIN,10,0);
width = (int) scrollbar__get (sb, SCR0LL_THICKNESS, 0);
display_panel = window_create(frame, PANEL,
WIN_BEL0W,
WIN_X,
WIN_VERTICAL_SCROLLBAR,
WIN_ROW_HEIGHT,
WI N__COLUMN_WI DTH,
WIN_ROW_GAP,
WIN_COLUMN_GAP,
WIN_LEFT_MARGIN,
WI N__TOP__MARGIN,
WIN_R0WS,
WI N__C0LUMN S,
0 );
window__set (display__panel, WIN__LEFT__MARGIN,
control_panel,
0 ,
sb,
64,
64,
10 ,
10 ,
width + 10,
10 ,
4,
4,
10 , 0 );
char *
get_selection()
{
static char filename [MAX__FILENAME_LEN];
Seln_holder holder;
Seln_request *buffer;
holder = seln_inquire(SELN_PRIMARY);
buffer = seln__ask (&holder, SELN__REQ_CONTENTS_ASCI1, 0, 0);
strncpy(filename, buffer->data + sizeof (Seln_attribute), MAX_FILENAME_LEN);
return (filename);
}
microsystems
Revision A, of May 9, 1988
412 SunView 1 Programmer’s Guide
A.4. tty Jo The following program demonstrates the use of ttysw_input (),
ttysw_output () and TTY escape sequences. These functions are explained
in Chapter 11, TTY Subwindows.
tty Jo creates a panel and a tty subwindow. You can send arbitrary character
sequences to the latter as input or output by manipulating panel items. There is
also a button that sends the current time within the escape sequence to set the
frame label. Try sending different sequences to the tty subwindow. Press
CTRL-R to see the difference between what appears on the screen and what was
input to the pseudo-tty. Also try starting the tool with a program such as vi as a
command line argument.
microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs (tty Jo) 413
/*****************************************************************************/
#ifndef lint
static char sccsid[] = (#)tty_io.c 1.4 87/11/19 Copyr 1986 Sun Micro";
#endif
/*****************************************************************************/
#include <stdio.h>
#include <suntool/sunview.h>
#include <suntool/tty.h>
#include <suntool/panel.h>
#define TEXT ITEM MAX LENGTH 25
Tty
Panel_item
char
static void
static void
static void
main(argc, argv)
int
argc;
char
**argv;
Frame
frame;
Panel
panel;
frame * window_create(NULL, FRAME,
FRAME_ARGS,
WIN_ERROR_MSG,
0 );
panel = window__c reate (frame, PANEL, 0) ;
/* set up a simple panel subwindow */
panel_create_itern(panel, PANEL_BUTTON,
PANEL_LABEL_IMAGE, panel_button_image(panel, "Input text", 11, 0),
PANEL_NOTIFY_PROC, input_text,
0 );
panel__create_item(panel, PANEL_BUTTON,
PANEL_LABEL_IMAGE, panel_button_image(panel, "Output text", 11, 0),
PANEL_NOTIFY_PROC, output_text,
0 );
text_item = panel__create_item (panel, PANEL_TEXT,
PANEL_LABEL_STRING, "Text:",
PANEL_VALUE, "Hello hello",
PANE L_VALUE_D ISP LAY_LENGTH, TEXT_I TEM_MAX_LENGTH,
0 );
panel_create_item(panel, PANEL_BUTTON,
PANEL_LABEL__IMAGE, panel_button__image (panel, "Show time", 11, 0),
PANEL_NOTIFY_PROC, output_time,
0 );
window_fit_height (panel) ;
argc, argv,
"Can't create tool frame".
tty;
text_item;
tmp_buf[80] ;
input_text() ;
output_text () ;
output_time () ;
m sun
Xr microsystems
Revision A, of May 9, 1988
414 SunView 1 Programmer’s Guide
/* Assume rest of arguments are for tty subwindow, except FRAME_ARGS leaves the
* program_name as argv[0], and we don't want to pass this to the tty subwindow.
*/
argv++;
tty = window_create(frame, TTY,
TTY_ARGV, argv,
WIN_ROWS, 24,
WIN_COLUMNS, 80,
0 );
window_fit (frame) ;
ttysw_input(tty, "echo my pseudo-tty is 'tty'\n H , 28);
window_main_loop (frame);
exit(0);
}
static void
input_text (item, event)
Panel__item item;
Event *event;
{
strcpy (tmp__buf, (char *) panel_get_value (text_itern) ) ;
ttysw_input(tty, tmp_buf, strlen(tmp_buf));
}
static void
output__text (item, event)
Panel_item item;
Event *event;
{
strcpy (tmp__buf, (char *) panel__get_value (text_item) ) ;
ttysw_output(tty, tmp_buf, strlen(tmp_buf));
}
m sun
XT microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs (tty Jo) 415
static void
output__time (item, event)
Panel item item;
Event
*event;
#include <sys/time.h>
#define ASCTIMELEN 26
struct timeval tp;
/* construct escape sequence to set frame label */
tmp_buf[0] = '\033';
tmp_buf[1] = ']';
tmp__buf [2 ] = ' 1' ;
tmp_buf[2 + ASCTIMELEN + 1] = f \033';
tmp_buf [2 + ASCTIMELEN + 2] - '\V;
gettimeofday(&tp, NULL);
strncpy(&tmp_buf[3], ctime(&tp.tv_sec) f ASCTIMELEN);
ttysw___output (tty, tmp_buf, ASCTIMELEN + 5);
J
Revision A, of May 9, 1988
416 SunView 1 Programmer’s Guide
A.5. fontjnenu The next program, fontjnenu , builds on several of the examples given in Chapter
12, Menus. Examples of the font menu it creates are shown below:
Frame
*ll
Family
Courier
■
Size
Serif
Bold
—
L
Italic
8 |
ffl?
CUR
10
~ ~—
12
Screen
14
16 g
18 1
Frame
Family
=*> |g
=3> |
Size
8
Bold
18
Italic
12
14
16
18
microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs (forUjnenu ) 417
/*****************************************************************************/
#ifndef lint
static char sccsid[] * M @(#)font_menu.c 1.2 86/09/15 Copyr 1986 Sun Micro";
#endif
/*****************************************************************************/
#include <suntool/sunview.h>
♦include <suntool/panel.h>
♦include <suntool/walkmenu.h>
void set_family () f set_size () , set_on_off () , toggle_on__of f () , open_fonts ();
Menu new_menu (), initialize_on_off ();
char *int_to_str();
extern char * sprintf();
extern char * malloc();
Panel_item feedback_item;
char *family, *size, *bold, ^italic;
Pixfont *cour, *serif, *apl, *cmr, ^screen;
/*****************************************************************************/
/* main */
/* First create the base frame, the feedback panel and feedback item. The */
/* feedback item is initialized to "gallant 8". */
/* Then get the frame's menu, call new_menu() to create a new menu with the */
/* original frame menu as a pullright, and give the new menu to the frame. */
/*****************************************************************************/
main(argc, argv)
int argc;
char *argv[];
{
Frame frame;
Panel panel;
Menu menu;
int defaults;
frame = window_create(NULL, FRAME, FRAME_LABEL, "Menu Test — Try frame menu.", 0);
panel = window_create(frame, PANEL, WIN_R0WS, 1, 0);
feedback_item = panel_create_item(panel, PANEL_MESSAGE, PANEL_LABEL_STRING, "", 0) ;
family = "Gallant", size = "8", bold - italic = "";
update_feedback();
/* remember if user gave -d flag */
if (argc >= 2) defaults = strcmp(argv[1], "-d") == 0;
menu = (Menu)window_get(frame, WIN_MENU);
menu = new_menu(menu, defaults);
window_set(frame, WIN_MENU, menu, 0);
window_main__loop (frame) ;
}
m sun
\T microsystems
Revision A, of May 9, 1988
418 SunView 1 Programmer’s Guide
/*****************************************************************************/
/* new_menu — returns a new menu with 'original menu' as a pullright. */
/*****************************************************************************/
Menu
new_menu(original_menu f defaults)
Menu original_menu;
int defaults;
{
Menu new_menu, family__menu, size_menu, on_off_menu;
int i;
/* create the on-off menu, which will be used as a pullright
* for both the bold and italic items to the new menu.
*/
on_off_menu = menu_create(MENU_STRING_ITEM, "On", 1,
MENU_STRING_ITEM, "Off", 0,
MENU_GEN_P ROC, initialize_on_off,
MENU_NOTIFY_PROC, set_on_off,
0 ); "
/* create the new menu which will eventually be returned */
open_fonts(); /* first open the needed fonts */
new_menu = menu_create(
MENU_P ULLRIGHT_ITEM,
"Frame”,
or iginal__menu,
MENU_P ULLRIGHT_ITEM,
"Family",
family_menu = menu_create (
MENU_ITEM,
MENU_STRING,
MENU_F0NT,
0 ,
MENU_ITEM,
MENU_STRING,
MENU_F0NT,
0 ,
MENUJETEM,
MENU__STRING,
MENU_F0NT,
0 ,
MENU_ITEM,
MENU_STRING,
MENU_F0NT,
0 ,
"Courier",
cour.
"Serif",
serif.
"aplAPLGIJ"
apl.
"CMR",
cmr.
m sun
\r microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs (fortijnenu) 419
MENU_ITEM,
MENU_STRING, "Screen",
MENU_FONT, screen,
0,
MENU_N0TIFY_PROC, set_family,
0 ),
MENU_P ULLRI GHT_I TEM,
"Size", size_menu = menu__create (0) ,
MENU_ITEM,
MENU_STRING, "Bold",
MENU_PULLRIGHT, on_off_menu,
MENU_NOTIFY_PROC, toggle_on_off,
MENU_CLIENT_DATA, &bold,
0,
MENU_ITEM,
MENU__STRING, "Italic",
MENU_P ULLRIGHT, on_off_menu,
MENU_NOTIFY_PROC, toggle_on_off,
MENU_CLIENT_DATA, Sitalic,
0,
0);
/* give each item in the family menu the size menu as a pullright */
for (i = (int)menu_get(family_menu, MENU_NITEMS); i > 0; —i)
menu_set (menu__get (family_menu, MENU_NTH_ITEM, i) ,
MENU_PULLRIGHT, size_menu, 0) ;
/* put non-selectable lines inbetween groups of items in family menu */
menu__s et (f amily__menu,
MENU_INSERT, 2, menu__create_item (MENU_STRING, "-",
MENU__I NACTIVE, TRUE,
0),
0);
menu_set (family_menu,
MENU_INSERT, 5, menu_get (family___menu, MENU_NTH_ITEM, 3),
0); "
/* The size menu was created with no items. Now give it items representing */
/* the point sizes 8, 10, 12, 14, 16, and 18. */
for (i = 8; i <= 18; i += 2)
menu_set(size_menu, MENU_STRING_ITEM, int_to_str(i), i, 0);
/* give the size menu a notify proc to update the feedback */
menu_set (size_menu, MENU_NOTIFY_PROC, set_size, 0);
m sun
V microsystems
Revision A, of May 9, 1988
420 SunView 1 Programmer’s Guide
/* if the user did not give the -d flag, make all the menus come
* up with the initial and default selections the last selected
* item, and the initial selection selected.
*/
if (!defaults) {
menu_set(new_menu,
MENU_DEFAULT_SELECTION, MENU_SELECTED,
MENU_INITIAL_SELECTION, MENU_SELECTED,
MENU_INITIAL_SELECTION_SELECTED, TRUE,
0 ); “
menu_set (family_menu,
MENU_DEFAULT_SELECTION, MENU_SELECTED,
MENU_INITIAL_SELECTION, MENU_SELECTED,
MENU_INITIAL_SELECTION_SELECTED, TRUE,
0 ); "
menu_set (size_menu,
MENU_DEFAULT_SELECTION, MENU_SELECTED,
MENU_INITIAL_SELECTION, MENU_SELECTED,
MENU_INITIAL_SELECTION_SELECTED, TRUE,
0 ); “
menu__set (on_off_menu,
MENU__DEF AULT_SELECT I ON, MENU_SELECTED,
MENU_INITIAL_SELECTION, MENU_SELECTED,
MENU_INITIAL_SELECTION_SELECTED, TRUE,
0 ); ‘
return (new_menu);
}
m sun
Xr microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs (fontjnenu ) 421
/*****************************************************************************/
/* set_family — notify proc for family menu. Get the current family and */
/* display it in the feedback panel. Note that we first get the value */
/* of the menu item. This has the side effect of causing any pullrights */
/* further to the right of mi to be evaluated. Specifically, the value of */
/* each family item is the value of its pullright — namely the size menu. */
/* When the size menu is evaluated, the notify proc set_size() is called, */
/* which updates the feedback for the size. */
/*****************************************************************************/
/*ARGSUSED*/
void
set_family (m, mi)
Menu m;
Menu_item mi;
{
menu_get(mi, MENU_VALUE); /* force pullrights to be evaluated */
family = menu_get(mi, MENU_STRING);
update_feedback();
}
/****************************************************************************V
/* set_size — notify proc for the size menu. */
/*****************************************************************************/
/*ARGSUSED */
void
set_size(m, mi)
Menu m;
Menu_item mi;
{
size = menu_get(mi, MENU_STRING) ;
update_feedback();
}
m sun
\r microsystems
Revision A, of May 9, 1988
422 SunView 1 Programmer’s Guide
/****************************************************************************/
/* initialize_on_off — generate proc for the on_off menu. */
/* The on-off menu is a pullright of both the bold and the italic menus. */
/* We want it to toggle — if its parent was on, it should come up with */
/* "Off" selected, and vice-versa. We can do that by first getting the */
/* parent menu item, then, indirectly through its client data attribute, */
/* seeing if the string representing the bold or italic state is null. */
/* If the string was null, we set the first item ("On") to be selected, */
/* else we set the second item ("Off") to be selected. */
/*****************************************************************************/
Menu
initialize_on_off(m, op)
Menu m; Menu_generate op;
{
Menu_item parent__mi;
char **name;
if (op != MENU_CREATE) return (m);
parent_mi = (Menu__item) menu_get (m, MENU_PARENT) ;
name = (char * *) menu_get (parent_mi, MENU_CLIENT_DATA);
if (**name == NULL)
menu_set (m.
D
i
_SELECTED,
i.
0);
menu_set (m.
MENU_
SELECTED,
2,
0);
return (m);
W sun
XT microsystems
Revision A, of May 9,1988
Appendix A — Example Programs (fontjnenu ) 423
/*****************************************************************************/
/* set_on_off — notify proc for on-off menu. */
/* Set the feedback string — italic or bold — appropriately depending on */
/* the current setting. Note that the "On" item was created to return a */
/* value of 1, and the "Off" item will return a value of 0. */
/*****************************************************************************/
void
set_on_off (m, mi)
Menu m; Menu_item mi;
{
Menu_item parent_mi;
char **name;
parent_mi = (Menu_item) menu_get (m, MENU_PARENT) ;
name = (char **)menu_get(parent__mi, MENU_CLIENT_DATA);
if (menu_get(mi, MENU_VALUE))
*name = (char *)menu_get(parent_mi, MENU_STRING);
else
*name * "";
update_feedback();
}
/*****************************************************************************/
/* toggle_on_off — notify proc for the "Bold" and "Italic" menu items. */
/* Using a notify proc for the menu item allows toggling without bringing */
/* up the on-off pullright. */
/*****************************************************************************/
/*ARGSUSED*/
void
toggle_on_off(m, mi)
Menu m;
Menu_item mi;
{
char **name;
name = (char **) menu_get (mi, MENU_CLIENT_DATA);
if (**name -= NULL)
*name = (char *)menu_get(mi f MENU_STRING);
else
*name = ""•;
update_feedback();
}
m sun
\r microsystems
Revision A, of May 9, 1988
424 SunView 1 Programmer’s Guide
r
update_feedback()
{
char buf[30];
sprintf(buf, "%s %s %s %s", bold, italic, family, size);
panel_set(feedback_item, PANEL_LABEL_STRING, buf, 0);
char *
int_jto_str (n)
{
char *r = malloc(4);
sprintf(r, "%d", n);
return (r);
void
open_fonts ()
{
cour = pf_open("/usr/lib/fonts/fixedwidthfonts/cour.r.10");
serif = pf_open("/usr/lib/fonts/fixedwidthfonts/serif.r.10");
apl = pf_open("/usr/lib/fonts/fixedwidthfonts/apl.r.10");
cmr = pf_open("/usr/lib/fonts/fixedwidthfonts/cmr.b.8");
screen - pf__open ("/usr/lib/fonts/fixedwidthfonts/screen, r. 11") ;
}
Revision A, of May 9, 1988
Appendix A — Example Programs (resize demo) 425
A.6. resize demo This program demonstrates how to resize the subwindows of a frame yourself if
you need to use a complicated topology.
The particular subwindow layout used here has four subwindows. One has a
fixed width and height in pixels, another has a fixed width in characters (using
the user-set default font), and the other two fill up the empty space. One of the
subwindows also has a scrollbar.
This program interposes in front of the frame’s client event handler. If the event
is WIN_RESIZE, the program’s own resize () procedure is called, which sets
the subwindow positions explicitly.
For a discussion of interposing and the Notifier, see Chapter 17, The Notifier.
The simpler case of using window attributes to layout subwindows is described
under Explicit Subwindow Layout in Chapter @NumberOf(window),
@TitleOf(window).
microsystems
Revision A, of May 9,1988
426 SunView 1 Programmer’s Guide
/★★★★a**********************************************************************/
#ifndef lint
static char sccsid[] = "%Z%%M% %I% %E% Copyr 1986 Sun Micro";
#endif
/★★a************************************************************************/
#include <suntool/sunview.h>
tinclude <suntool/canvas.h>
#include <suntool/scrollbar.h>
Canvas Canvas_l, Canvas_2, Canvas_3, Canvas_4;
Pixwin *Pixwin_l, *Pixwin__2, *Pixwin_3, *Pixwin_4;
Rect framerect;
PIXFONT *font;
extern char * sprintf ();
/*
* font macros:
* font_offset(font)
★
★
*
*
■k
*/
font_height (font)
gives the vertical distance between
the font origin and the top left corner
of the bounding box of the string displayed
(see Text Facilities for Pixrects in the
Pixrect Reference Manual)
gives the height of the font
#define font__offset(font) (-font->pf_char['n f ].pc_home.y)
#define font_height(font) (font->pf__defaultsize.y)
/*
* SunView-dependent size definitions
*/
#define LEFT_MARGIN 5
#define RIGHT_MARGIN 5
#define BOTTOM_MARGIN 5
#define SUBWINDOW_SPACING
subwindows */
/* margin on left side of frame *
/* margin on right side of frame */
/* margin on bottom of frame */
5 /* space in between adjacent
/*
* application-dependent size definitions
*/
tdefine CANVAS_1_WIDTH 320 /* width in pixels of canvas 1 */
#define CANVAS_1_HEIGHT 160 /* height in pixels of canvas 1 */
fdefine CANVAS 3 COLUMNS 30 /* width in characters of canvas 3 */
main (argc, argv)
int argc;
char **argv;
{
Frame frame;
static Notify_value catch_resize();
static void draw_canvas_l () f draw_canvas_3 ();
/*
* create the frame and subwindows, and open the font
m sun
\r microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs (resize demo ) 427
}
* no size attributes are given yet
*/
frame = window_create(NULL, FRAME,
FRAME_ARGS, argc, argv,
WIN_ERROR_MSG, "Can't create tool frame",
FRAME_LABEL, "Resize Demo",
0 ) ;
Canvas_l = window_create(frame, CANVAS,
CANVAS_RESI ZE_PR0C, draw_canvas_l,
0 );
Canvas_2 = window_create (frame, CANVAS,
0 );
Canvas_3 = window_create(frame, CANVAS,
WIN_JVERTICAL__SCROLLBAR, scrollbar_create (
SCROLL_P LACEMENT, SCROLL_EAST,
0 ),
CANVAS_RESIZE_PROC, draw_canvas_3,
0 );
Canvas_4 = window_create(frame, CANVAS,
0 );
Pixwin_l = canvas_j?ixwin (Canvas_l) ;
Pixwin_2 = canvas_pixwin(Canvas_2);
Pixwin_3 = canvas_pixwin (Canvas__3) ;
Pixwin__4 = canvas_j?ixwin (Canvas_4) ;
font = pf__default () ;
/*
* now that the frame and font sizes are known, set the initial
* subwindow sizes
*/
resize (frame) ;
/*
* insert an interposer so that whenever the window changes
* size we will know about it and handle it ourselves
*/
(void) not if y_interpose_event_func (frame, catch__resize, NOTIFY__SAFE) ;
* start execution
*/
window_main_loop (frame) ;
exit (0);
/*
* catch_resize
*
interposed function which checks all input events passed to the frame
for resize events; if it finds one, resize () is called to refit
the subwindows; checking is done AFTER the frame processes the
event because if the frame changes its size due to this event (because
the window has been opened or closed for instance) we want to fit
the subwindows to the new size
m sun
Xr microsystems
Revision A, of May 9, 1988
428 SunView 1 Programmer’s Guide
*/
static Notify_value
catch_resize(frame, event, arg, type)
Frame frame;
Event *event;
Notify_arg arg;
Notify__event_type type;
{
Notify_value value;
value = notify_next_event__func(frame, event, arg, type);
if (event_action(event) == WIN_RESIZE)
resize(frame);
return (value);
}
/*
* resize
*
* fit the subwindows of the frame to its new size
*/
resize(frame)
Frame frame;
{
Rect *r;
int canvas_3__width; /* the width in pixels of canvas 3 */
int stripeheight; /* the height of the frame's name stripe */
/* if the window is iconic, don't do anything */
if ((int)window_get(frame, FRAME_CLOSED))
return;
/* find out our new size parameters */
r = (Rect *) window_get (frame, WIN__RECT) ;
framerect = *r;
stripeheight = (int) window_get(frame, WIN_TOP_MARGIN) ;
canvas_3_width = CANVAS_3_C0LUMNS * font->pf_defau It size .x
+ (int) scrollbar_get(SCROLLBAR, SCROLL_THICKNESS);
window_set(Canvas_2,
WIN_X,
WIN_Y,
WIN_WIDTH,
WIN HEIGHT,
0 ,
0 ,
framerect. r__width - canvas_3_width
- LEFT_MARGIN - SUBWINDOW_SPACING
- RIGHT_MARGIN,
framerect. r__height - CANVAS_1_HEIGHT
- stripeheight - SUBWINDOW_SPACING -
B0TT0M_MARGIN,
0 );
window_set(Canvas_l,
WIN_X, 0,
WIN_Y, framerect .r__height - CANVAS_1_HEIGHT -
SUBWINDOW_SPACING - stripeheight,
WIN WIDTH, CANVAS_1_WIDTH,
m sun
Xr microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs (resize demo ) 429
WIN_HEIGHT,
0 );
window_set(Canvas_4,
WIN_X,
WIN_Y,
WIN_WIDTH,
WIN_HEIGHT,
0 );
window_set (Canvas_3,
WIN_X,
WIN_Y,
WIN_WIDTH,
WIN_HEIGHT,
CANVAS_1_HEIGHT,
CANVAS__1__WI DTH + SUBWINDOW_SPACING,
framerect. r_height - CANVAS_1_HEIGHT
- SUBWI NDOW_SP ACING - stripeheight,
framerect. r_width - canvas_3_width
- CANVAS_1_WIDTH - LEFT_MARGIN
- 2 * SUBWINDOW_SPACING - RIGHT_MARGIN,
C AN VA S_ 1_HE IGHT f
framerect. r_width - canvas_3_width
- LEFT_MARGIN - SUBWINDOW_SPACING,
0 ,
canvas_3_width,
framerect . r__height - stripeheight
- B0TT0M_MARGIN,
/*
* draw_canvas_l
* draw_canvas_3
*
* draw simple messages in the canvases
*/
static void
draw_canvas_l()
{
char buf[64];
}
sprintf(buf, "%d by %d pixels",
CANVAS_1_WIDTH, CANVAS_1_HEIGHT);
pw_text(Pixwin_l, 5, font_offset (font), PIX_SRC, font,
"This subwindow is always ");
pw_text (Pixwin__l, 5, font_offset(font) + font_height (font) ,
PIX_SRC, font, buf);
static void
draw_canvas_3()
{
char buf[64];
sprintf(buf, "%d characters wide".
pw__text (Pixwin_3,
pw_text(Pixwin_3,
}
CANVAS_3_C0LUMNS);
5, font__offset (font) , PIX_SRC, font,
"This subwindow is always
5, font_offset(font) + font_height(font)
font, buf);
PIX_SRC,
Revision A, of May 9, 1988
430 SunView 1 Programmer’s Guide
A.7. detool detool is a simple reverse-polish notation calculator which demonstrates how to
use pipes to write a SunView-based front end for an existing non-SunView pro¬
gram. detool consists of a panel with buttons for each digit, the four arithmetic
operations, and an enter key. The digits you hit are displayed in a message item
and are sent via a pipe to ,dc(l) a UNIX desk calculator. When dc computes an
answer, it is sent back to detool via a second pipe and it is displayed.
Note also the use of a single notify procedure for all of the digit buttons. The
actual digit associated with each button is stored as the client data for each panel
item, so the notify procedure can determine which button was pressed by looking
at the client data. This value is then passed directly to dc. The operation buttons
also all use a single notify procedure.
When you run detool, remember that it is a reverse-polish notation calculator.
For instance, to compute 3*5 you must hit the buttons 3, Enter, 5, and * in that
order. If you prefer infix notation, you could easily adapt detool to use bc(l)
instead of dc.
microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs {detool) 431
/****************************************************************/
#ifndef lint
static char sccsid[] = M @(#)detool.c 1.4 86/09/15 Copyr 1986 Sun Micro";
#endif
/****************************************************************/
♦include <stdio.h>
♦include <suntool/sunview.h>
♦include <suntool/panel.h>
static
Frame
frame;
static
Panel
panel;
static
Panel_
item digit_item[10]
, enter_
item;
static
Panel_
item add_item, sub_
item, mul_item, div__item;
static
Panel_
item display_item;
static
char
display_buf[512]
=
ii ii.
t
/* storage for the
* numbers currently on
* the display (stored as
* a string) */
static
FILE
*fp_tochild;
/*
fp of
pipe to child (write
*
data
on it) * /
static
FILE
*fp__fromchild;
/*
fp of
pipe from child (read
*
data
from it) */
static
int
tochild;
/*
associated file descriptors */
static
int
fromchild;
static
int
chi1dpid;
/*
pid of child process */
static
int
dead =* 0;
/*
set to 1 if child process has
★
died
*/
main(arge, argv)
int arge;
char **argv;
{
static Notify_value pipe_reader();
static Notify_value dead__child() ;
frame = window_create(NULL, FRAME,
FRAME_ARGS, arge, a rgv,
WIN_ERROR__MSG, "Cannot create frame",
FRAME_LABEL, "detool - RPN Calculator",
0 );
panel = window_create (frame, PANEL,
0 );
create_panel_iterns (panel) ;
window_fit (panel) ;
window_fit (frame) ;
/* start the child process and tell the notifier about it */
start_dc () ;
/*
* note that notify_set__input_func takes a file descriptor,
* not a file pointer used by the standard I/O library
m sun
Nr microsystems
Revision A, of May 9,1988
432 SunView 1 Programmer’s Guide
*/
(void) not if y_set_input_func (frame, pipe_reader, fromchild);
(void) notify_set_wait3__func (frame, dead__child, childpid);
window__main_loop (frame) ;
exit (0);
static
create_panel_items (panel)
Panel panel;
{
int
char
static void
static struct
int
}
c;
name [2] ;
digit_proc ()
col, row;
positions[10]
op_proc () ;
{ 0 , 3 }, {
o.
0
{
6,
0
},
{
12,
0
},
{
o.
1
>,
{
6,
1
},
{
12,
1
},
{
};
0 ,
2
{
6,
2
>,
{
12,
2
)
name[l] « ' \0 ';
for (c =0; c < 10; C++) {
name[0] = c + 'O';
digit_item[c] * panel__create_itern (panel, PANEL_BUTTON,
PANEL_LABEL_IMAGE, panel_button_image(panel, name, 3, 0),
P ANEL__NOTIFY_PR0C, digit_proc,
P ANEL__CL I ENT_D ATA, (caddr_t) (c + '0'),
PANE L_LABE L_X, ATTR_COL(positions[c] .col),
PANE L_LABE L_Y, ATTR_R0W(positions[c] .row),
0);
}
add_item = panel__create_item(panel, PANEL_BUTTON,
PANEL_LABEL_IMAGE, panel_button_image(panel, "+", 3, 0),
PANEL_NOTIFY_PROC, op_proc,
PANEL_CLIENT_DATA, (caddr_t) ' +' ,
PANE L__LABE L__X, ATTR__C0L (18),
PANEL_LABEL_Y, ATTR_R0W (0) ,
0);
sub_item = panel_create_item(panel, PANEL_BUTTON,
PANEL_LABEL_IMAGE, panel_button_image(panel, " - ", 3, 0),
PANEL_NOTIFY_PR0C, op_proc,
PANEL_CLIENT_DATA, (caddr_t) ',
PANE L_LABE L_X, ATTR_COL(18),
PANE L_LABE L_Y, ATTR_R0W(1),
0);
mul_item = panel_create_item(panel, PANEL_BUTTON,
PANEL_LABEL_IMAGE, panel_button_image (panel, 3, 0),
PANEL_NOT IFY_PR0C, op_proc,
PANEL_CLIENT_DATA, (caddr_t) '*',
PANE L_LABE L_X, ATTR_C0L(18),
PANE L_LABE L_Y, ATTR_ROW(2),
0);
div_item = panel_create_item (panel, PANEL_BUTTON,
PANEL_LABEL_IMAGE, panel_button_image (panel, 3, 0),
P ANEL_N OT IF Y__PR0C, op__proc.
w ^ un
\r microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs (< detool) 433
P ANEL__CL I ENT__DATA, (caddr_t) ' /' ,
PANEL_LABEL_X, ATTR_COL (18) ,
PANEL_LABEL_Y , ATTR_ROW (3) ,
0);
enter_item = panel_create_item(panel, PANEL_BUTTON,
PANEL_LABEL_IMAGE, panel_button_image(panel, "Enter", 7, 0),
PANEL_NOTIFY_PROC, op_proc,
PANEL_CLIENT_DATA, (caddr_t) ' ' ,
PANEL_LABEL__X, ATTR_COL (6) ,
PANEL_LABEL_Y, ATTR_R0W (3) ,
0);
display__item = panel_create_item(panel, PANEL_MESSAGE,
PANEL_LABE L_STRING, "0",
PANE L_LABE L_X, ATTR_COL(0),
PANE L_LABE L_Y, ATTR_ROW(4),
0);
/* callback procedure called whenever a digit button is pressed */
static void
digit__proc (item,
Panel_item
Event
{
int
event)
item;
*event;
digit__name
char
buf[2];
(int) panel_get(item,
PANEL_CLIENT_DATA);
buf[0] = digit_name; /* display digit */
buf[1] = '\0';
streat(display_buf, buf);
panel_set(display_item, PANEL_LABEL_STRING, display__buf, 0);
send_to__dc (digit_name); /* send digit to dc */
/*
* callback procedure called whenever an operation button is
* pressed
*/
static void
op_proc(item, event)
Panel_item item;
Event *event;
{
int op_name = (int) panel_get(item,
PANEL__CLIENT_DATA) ;
display__buf [0] = '\0';
s end_to_dc (op_name) ;
if (item != enter_item)
send_to_dc('p');
send_to_dc( f \n');
/* don't erase display yet; wait
* until the answer comes back */
/* send a p so the answer will be
* printed by dc */
w sun
\r microsystems
Revision A, of May 9, 1988
434 SunView 1 Programmer’s Guide
/*
* start the child process
*/
static
start_dc ()
{
int pipeto[2], pipefrom [2];
int c f numfds;
if (pipe(pipeto) < 0 || pipe(pipefrom) < 0) {
perror("dctool");
exit (1);
}
switch (childpid - fork()) {
case -Is
perror("dctool");
exit (1);
case 0: /* this is the child process */
/*
* use dup2 to set the child's stdin and stdout to the
* pipes
*/
dup2(pipeto[0] f 0);
dup2(pipefrom[l] , 1) ;
/*
* close all other fds (except stderr) since the child
* process doesn't know about or need them
*/
numfds * getdtablesize();
for (c = 3; c < numfds; C++)
close (c);
/* exec the child process */
execl("/usr/bin/dc", "dc", 0);
perror("dctool (child)"); /* shouldn't get here */
exit(1);
default: /* this is the parent */
close(pipeto[0]);
close(pipefrom[l]);
tochild = pipeto[1];
fp_tochild = fdopen(tochild f "w");
fromchild = pipefrom[0];
fp_fromchild = fdopen(fromchild, "r");
/*
* the pipe to dc must be unbuffered or dc will not get
* any data until 1024 characters have been sent
*/
setbuf(fp_tochild, NULL);
» sun
V microsystems
Revision A, of May 9,1988
Appendix A — Example Programs ( detool) 435
break;
}
}
/*
* notify proc called whenever there is data to read on the pipe
* from the child process; in this case it is an answer from dc,
* so we display it
*/
static Notify_value
pipe_reader(frame, fd)
Frame frame;
int fd;
{
char buf[512];
fgets(buf, 512, fp_fromchild);
buf[strlen(buf) - 1] = f \0';/* remove newline */
panel_set (display_item, PANEL_LABEL_STRING, buf, 0);
display_buf[0] = '\0';
return (N0TIFY_D0NE);
}
/*
* notify proc called if the child dies
*/
static Notify_value
dead_chiId(frame, pid, status, rusage)
Frame frame;
int pid;
union wait *status;
struct rusage *rusage;
{
panel_set (display_item, PANEL_LABEL_STRING, "Child died! ••, 0) ;
dead =1;
/*
* tell the notifier to stop reading the pipe (since it is
* invalid now)
*/
(void) notify_set_input_func (frame, NOTIFY_FUNC_NULL,
fromchild);
close(tochild);
close(fromchild);
return (N0TIFY_D0NE);
}
/* send a character over the pipe to dc */
static
s end_t o__dc (c)
char c;
{
if (dead)
panel__set (display__item.
m sun
Xr microsystems
Revision A, of May 9, 1988
436 SunView 1 Programmer’s Guide
PANEL_LABEL_STRING, "Child is dead!",
0 );
else
putc (c, fp_tochild) ;
}
Asun
XT microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs {typein) 437
A.8. typein
This program shows how to replace the functionality of the Graphics Tool and
gfxsw package previously available under Sun Windows, typein provides a tty
emulator for interaction with the user and a canvas to draw on. To demonstrate
it, a simple application is included which allows the user to input coordinates in
the tty emulator and then draws the vectors in the canvas.
typein uses a tty subwindow and a canvas. Normally, the tty subwindow is used
to allow a child process to run in a window; in this case, we would like the same
process to write in that window. To accomplish this, we tell the tty subwindow
not to fork a child process with the tty_argv_do_NOT_fork value for
TTY ARGV. typein uses dup2(2) to set its stdin and stdout to the TTY_FD.
When the user types something in the tty subwindow, typein 's read_input ()
routine is called.
NOTE When using this mechanism, be careful of the following problems. First, you
must use the Notifier (unlike the old gfxsw). Second, if you use the standard I/O
package, be sure to either use f flush carefully or to remove all buffering with
setbuf because the package will think you are sending data to a file and not to
a tty. Finally, be sure you never block on a read because the program will hang
(either use non-blocking I/O or only read one line at a time).
XT microsystems
Revision A, of May 9, 1988
438 SunView 1 Programmer’s Guide
/*********************************************************/
#ifndef lint
static char sccsid[] = "@(#)typein.c 1.5 87/01/07 Copyr 1986 Sun Micro";
#endif
/*********************************************************/
♦include <stdio.h>
♦include <suntool/sunview,h>
♦include <suntool/canvas.h>
♦include <suntool/tty.h>
♦include <ctype.h>
static Frame
static Canvas
static Tty
static Pixwin
frame;
canvas;
tty;
*pw;
static Notify_client my_client;
♦define STDIN_FD 0
♦define STD0UT_FD 1
♦define BUFSIZE 1000
main(argc, argv)
int argc;
char **argv;
{
static Notify_value read_input ();
int tty_fd;
frame = window_create(NULL, FRAME,
FRAME__ARGS, argc, argv,
WIN_ERROR_MSG, "Cannot create frame",
FRAME_LABEL, "typein",
0 );
tty = window__create (frame, TTY,
WI N_PERCENT__HE IGHT, 50,
T TY_ARGV, TTY_ARGV_DO_NOT_FORK,
0 );
tty_fd = (int) window_get (tty, TTY_TTY_FD) ;
dup2(tty_fd, STD0UT_FD);
dup2(tty_fd, STDIN_FD);
canvas = window_create(frame, CANVAS,
0 );
pw = canvas_pixwin(canvas);
/*
* Set up a notify proc so that whenever there is input to read on
* stdin (fd 0), we are called to read it.
* Notifier needs a unique handle: give it the address of tty.
*/
my_client = (Notify_client) &tty;
notify_set_input_func(my_client, read__input, STDIN_FD);
printf("Enter first coordinate:\nx? ");
m sun
Xr microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs ( typein) 439
window_main_loop (frame) ;
exit (0);
/*
* This section implements a simple application which writes prompts to
* stdin and reads coordinates from stdout, drawing vectors with the
* supplied coordinates. It uses a state machine to keep track of what
* number to read next.
*/
#define GET_X_1 0
#define GET_Y__1 1
#define GET_X_2 2
#define GET Y 2 3
int state = GET_X_1;
int xl, yl, x2, y2;
/* ARGSUSED */
static Notify__value
read_input (client, in_fd)
Notify_client client;
int in_fd;
{
char buf[BUFSIZE];
char *ptr, *gets();
/* unused since this must be from ttysw */
/* unused since this is stdin */
ptr = gets(buf); /* read one line per call so that we
don't ever block */
/* ~ does this matter any more?? */
/* handle end of file */
if (ptr==NULL) {
/* Note: could have been a read error */
window_set(frame, FRAME_N0_C0NFIRM, TRUE, 0);
window_done(tty);
} else {
switch (state) {
case GET__X_1:
if (sscanf(buf, "%d", &xl) != 1) {
printf("Illegal value!\nx? ");
fflush(stdout);
} else {
printf("y? ");
fflush(stdout);
state++;
}
break;
case GET_Y_1:
if (sscanf(buf, ’^d”, &yl) != 1) {
printf("Illegal value!\ny? ");
fflush(stdout);
} else {
printf("Enter second coordinate:\nx? ");
fflush(stdout);
state++;
}
break;
case GET X 2:
m sun
\r microsystems
Revision A, of May 9, 1988
440 SunView 1 Programmer’s Guide
if (sscanf(buf, "%d", &x2) != 1) {
printf("Illegal value!\nx? ");
fflush(stdout);
} else {
}
break;
printf("y? ");
fflush(stdout);
state++;
case GET__Y__2:
if (sscanf(buf, "%d", &y2) != 1) {
} else
printf("Illegal value!\ny? ");
fflush(stdout);
{
printf("Vector from (%d, %d) to (%d f %d)\n" f
xl r ylf x2 , y2);
pw_vector(pw f xl f yl f x2, y2 f PIX_SET f 1);
printf("\nEnter first coordinate:\nx? ");
fflush(stdout);
state = GET_X_1;
}
break;
}
}
return(NOTIFY_DONE);
}
®sun
Xr microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs ( coloredit ) 441
A.9. Programs that
Manipulate Color
The following two programs work with color. You can run them on a mono¬
chrome workstation to no ill-effect, but you won’t see much of interest.
The techniques employed by these two programs are explained in the Color sec¬
tion of Chapter 7, Imaging Facilities: Pixwins.
When using these programs, try invoking them with different colors using the
frame’s command line arguments. Also, run showcolor (listed in the pixwin
chapter) to see how the screen’s colormap changes as different color programs
are run simultaneously.
coloredit
The first program, coloredit , puts up sliders that let the user modify its colors.
Revision A, of May 9,1988
442 SunView 1 Programmer’s Guide
/***************************************************************************/
#ifndef lint
static char sccsid[] * "@ (♦)coloredit.c 1.4 86/09/15 Copyr 1986 Sun Micro”;
#endif
/***************************************************************************/
♦include <suntool/sunview.h>
♦include <suntool/panel.h>
♦include <suntool/canvas.h>
♦define MYFRAME 0
♦define MYPANEL 1
♦define MYCANVAS 2
/* colormap sizes for the three windows. Canvas is still the biggest
mycms_sizes[3] = {
2, 2, 4
};
♦define MYCMS_SIZE 4
/* color arrays; initialize them with the canvas colors */
unsigned char red[MYCMS_SIZE] = {0, 0, 255, 255};
unsigned char green[MYCMS_SIZE] = {0, 255, 0, 192};
unsigned char blue[MYCMS_SIZE] = {255, 0, 0, 192};
*/
static void
static void
static void
static void
static void
static void
getcms ();
setcms () ;
cycle () ;
editcms () ;
set_color () ;
change_value();
Panel_item text_item;
Panel_item color_item;
Panel_item red_item, green_item, blue_item;
Pixwin *pixwins[3];
Pixwin *pw;
main(argc, argv)
int
char
{
Frame
Panel
Canvas
argc;
**argv;
base__frame;
panel;
canvas;
Attr__avlist sliderdefaults;
/* the cmsname is copied, so this array can be reused */
char cmsname[CMS_NAMESIZE];
int counter;
int xposition;
char buf[40];
base_frame = window_create(NULL, FRAME,
FRAME LABEL, "coloredit”.
m sun
XT microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs (coloredit) 443
FRAME_ARGS, argc, argv,
0 );
/* set up the panel */
panel = window_create(base_frame, PANEL,
0 ); "
/* create a reusable attribute list for my slider attributes
sliderdefaults = attr_create_list(
PANEL_SHOW_ITEM,
P ANEL_M I N__VALUE ,
P ANEL_MAX__VALUE ,
P ANEL__SL I DER_WI DTH,
PANEL_SHOW_RANGE,
PANEL_SHOW_VALUE,
P ANEL_N0T IF Y__LEVEL,
0 );
TRUE,
0 ,
255,
512,
TRUE,
TRUE,
PANEL_ALL,
*/
panel_create_item(panel, PANEL_CYCLE,
PANEL__LABEL_STRING,
PANEL__VALUE,
PANEL_CHOICE_STRINGS,
PANEL_N0T IFY_PR0C,
0 );
"Edit colormap:",
MYCANVAS,
"Frame", "Panel",
editerns.
"Canvas",
Or
text_item = panel_create__item(panel, PANEL_TEXT,
P ANEL_VALUE_D ISP LAY__LEN GTH, CMS_NAMESI ZE,
PANEL_VALUE_STORED_LENGTH, CMS_NAME SIZE,
0 );
color_item = panel_create_item(panel, PANEL_SLIDER,
ATTR_LIST,
PANEL_LABEL_STRING,
PANEL_NOTIFY_PROC,
0 );
sliderdefaults,
"color:",
set_color.
red_item = panel_create_itern (panel, PANEL_SLIDER,
ATTR_LIST,
PANEL_LABEL_STRING,
PANEL_NOTIFY_PROC,
0 );
sliderdefaults,
" red:",
change__value,
green_item = panel_create_item(panel, PANEL_SLIDER,
ATTR_LIST, sliderdefaults,
PANEL_LABEL_STRING, "green:",
PANEL_NOTIFY_PROC, change_value,
0 );
blue_item = panel_create__item (panel, PANEL_SLIDER,
ATTR__LIST, sliderdefaults,
P ANEL__LABE L__S TRI NG, " blue:",
P ANEL_NOT I FY___PROC, change_value,
0 );
panel_create_item(panel, PANEL_BUTTON,
PANEL_LABEL_IMAGE,
m sun
Xr microsystems
Revision A, of May 9, 1988
444 SunView 1 Programmer’s Guide
panel__button_image (panel, "Cycle colormap", 12, NULL),
PANE L_N OTIFY_PROC, cycle,
0 );
window_fit(panel);
window_fit_width(base_frame);
/* free the slider attribute list */
free(sliderdefaults);
/* set up the canvas */
canvas = window_create (base_frame, CANVAS, 0);
/* get pixwins */
pixwins[MYFRAME] = (Pixwin *) window_get(base_frame, WIN_PIXWIN);
pixwins[MYPANEL] = (Pixwin *) window_get(panel, WIN_PIXWIN);
pw = pixwins[MYCANVAS] = (Pixwin *) canvas_pixwin(canvas);
/* set up the canvas' colormap */
sprintf(cmsname, "coloredit%D", getpid());
pw_set cmsname(pw, cmsname);
pw_putcolormap(pw, 0, mycms_sizes[MYCANVAS], red, green, blue);
/* draw in the canvas */
/* don't draw color 0 — it is the background */
for (counter = 1; counter < mycms_sizes[MYCANVAS]; counter+f) {
xposition = counter * 100;
pw_rop(pw, xposition, 50, 50, 50,
PIX_SRC | PIX__C0L0R(counter) , NULL, 0, 0);
sprintf(buf, "%d", counter);
pw__text (pw, xposition + 5, 70, PIX_SRC ~ PIX_DST, 0, buf);
}
pw__text (pw, 100, 150,
PIX_SRC | PIX_COLOR(mycms_sizes[MYCANVAS] -1), 0,
"This is written in the foreground color");
/* initialize to edit the first canvas color */
editcms(NULL, MYCANVAS, NULL);
window_main_loop (base_frame) ;
exit (0);
static int cur_cms = -1;
/* ARGSUSED */
static void
editcms(item, value, event)
Panel_item item;
unsigned int value;
Event *event;
{
int planes;
struct colormapseg cms;
char cmsname[CMS_NAMESIZE];
if (value == cur_cms)
return;
m sun
Xr microsystems
Revision A, of May 9,1988
Appendix A — Example Programs (coloredit) 445
cur_cms = value;
/* get the new cmsname */
pw_getcmsname(pixwins[cur_cms], cmsname);
panel_set_value (text_item, cmsname) ;
pw = pixwins [cur_cms] ;
/* get the new colormap */
/*
* first have to get its size there is NO DOCUMENTED procedure to do
* this.
*/
pw_getcmsdata(pw, &cms, &planes);
pw_getcolormap(pw, 0, cms.cms^size, red, green, blue);
panel_set (color__item,
PANEL_VALUE, 0,
PANEL_MAX_VALUE, cms.cms_size - 1,
0 );
/* call the proc to set the colors */
set_color(NULL, 0, NULL);
int cur_color;
/* ARGSUSED */
static void
set__color (item, color, event)
Panel_item item;
unsigned int color;
struct inputevent *event;
{
panel_set_value(red_item, red[color]);
panel_set_value(green_item, green[color]);
panel_set_value(blue_item, blue[color]);
cur_color = (unsigned char) color;
}
/* ARGSUSED */
static void
change_value(item, value, event)
Panel__item item;
int value;
struct inputevent *event;
{
if (item == red_item)
red[cur_color] = (unsigned char) value;
else if (item == green_item)
green[cur_color] = (unsigned char) value;
else
blue[cur_color] = (unsigned char) value;
/*
* pw_putcolormap expects arrays of colors, but this only sets one
* color
*/
pw_jputcolormap (pw, cur_color, 1,
&red[cur_color], Sgreen[cur_color], &blue[cur_color]);
W sun
Xr microsystems
Revision A, of May 9, 1988
446 SunView 1 Programmer’s Guide
/* ARGSUSED */
static void
cycle(item, event)
Panel_item item;
Event *event;
{
pw_cyclecolormap (pw, 1, 0, mycms_sizes [cur_cms]) ;
}
^_ _ _—-
Revision A, of May 9, 1988
Appendix A — Example Programs ( animalecolor ) 447
animatecolor
This program demonstrates smooth animation via the technique of software
double-buffering. Two colormaps for the canvas are set up so that while one is
being written two, the other is being displayed. This allows smoother animation.
The routines that set up the colormaps and swap them, doublebuf f_init ()
and doublebuf f_swap (), are general enough to be used in other programs
that alternate two colormaps. You need only set up a similar colorstuf f
structure to use these routines in another program.
The logic involved in creating the colormaps is complex. The colormaps created
for animatecolor are given in the table Sample Colormap to Isolate Planes in the
pixwin chapter.
microsystems
Revision A, of May 9, 1988
448 SunView 1 Programmer’s Guide
/***************************************************************/
tifndef lint
static char sccsid[] = "@(#)animatecolor.c 1.4 88/03/09 Copyr 1986 Sun Micro";
#endif
/***************************************************************/
#include <suntool/sunview.h>
tinclude <suntool/canvas.h>
/***************************************************************/
/* You set MYCOLORS & MYNBITS according to how many colors */
/* you are using; rest is just boilerplate, more or less; */
/* it you define your colors. */
/★a*************************************************************/
/*
* define the colors I want in the canvas; max 16, must be a
* power of 2
*/
#define MYCOLORS 4
/*
* define the number of bits my colors take up — MYCOLORS log 2;
* maximum for animation to be possible is half screen's bits per
* pixel — 4 bits on current Sun color displays.
*/
#define MYNBITS 2
/*
* to "hide" one set of planes while displaying another takes a
* large cms — the square of the number of colors
*/
#define MYCMS_SIZE (MYCOLORS * MYCOLORS)
/*
* when you write out a color pixel, you must write the color in
* the appropriate planes. This macro writes it in both sets
*/
#define usecolor(i) ( (i) | ((i) « colorstuff.colorbits) )
struct colorstuff {
/* desired colors */
unsigned char redcolors[MYCOLORS] ;
unsigned char greencolors[MYCOLORS];
unsigned char bluecolors[MYCOLORS];
/* number of bits the desired colors take up */
int colorbits;
/* colormap segment size */
int cms__size;
/* 2 colormaps to support it */
unsigned char red[2][MYCMS_SIZE];
unsigned char green[2][MYCMS_SIZE];
unsigned char blue[2][MYCMS_SIZE];
/* 2 masks to support it */
int enable__0_mask;
int enable_l__mask;
/* current colormap — 0 or 1 */
int cur_buff;
/* plane mask to control which planes are written to */
int plane_mask;
Revision A, of May 9, 1988
Appendix A — Example Programs ( animatecolor ) 449
In¬
struct colorstuff colorstuff
/* desired red colors */
/* desired green colors */
/* desired blue colors */
{
{0, 0, 255,
{0, 255, 0,
{255, 0, 0,
/* number of planes these colors take up */
MYNBITS,
/* colormap segment size */
MYCMS_SIZE,
/* rest filled in later */
};
255},
192},
192},
static void resize_proc();
/* stuff needed to do random numbers */
extern
void
s random () ;
extern
int
getpid() ;
extern
long
random();
extern
char
* sprint f () ;
static Notify_value my_frame_interposer();
static Notify_value my_draw();
static Pixwin *pw;
static int times_drawn;
static int Xmax, Ymax;
main (argc, argv)
int argc;
char **argv;
{
F rame ba s e_f rame;
Canva s canva s;
base_frame = window_create(NULL, FRAME,
FRAME_LABEL, "animatecolor”,
FRAME_ARGS, argc, argv,
0 );
canvas = window_create(base_frame, CANVAS,
CANVAS_RETAINED, TRUE,
CANVAS_RE SIZE_PR0C, re siz e_proc,
0 );
pw = (Pixwin *) canvas_pixwin(canvas);
/* set up the canvas' colormap */
doublebuff_init(Scolorstuff);
/* run the drawing routine as often as possible */
(void) notify_set_itimer_func (base__frame, my__draw,
ITIMER_REAL,
&NOTIFY_POLLING_ITIMER,
( (struct itimerval *) 0) );
/* initialize the random function */
m sun
\r microsystems
Revision A, of May 9, 1988
450 SunView 1 Programmer’s Guide
srandom(getpid ());
window_main_loop (base_f rame) ;
exit(0);
}
/* ARGSUSED */
static Notify__value
my_draw(client, itimer_type)
Notify_client client;
int itimer__type;
{
/*
* draw the squares, then swap the colormap to animate them
V
#define SQUARESIZE 50
#define MAX_VEL (SQUARESIZE / 5)
/* number of squares to animate */
#define NUMBER (MYCOLORS - 1)
static int
static int
static int
int
posx[NUMBER], posy[NUMBER];
vx[NUMBER], vy[NUMBER];
prevposx[NUMBER], prevposy[NUMBER];
i;
/* set the plane mask to be that which we are not viewing */
pw_putattributes(pw, (colorstuff.cur_buff == 1) ?
&(colorstuff.enable_l_mask): &(colorstuff.enable_0__mask));
/* write to invisible planes */
for (i - 0; i < NUMBER; i++) {
if (!times_drawn) {
/* first time drawing */
posx[i] = (i + 1) * 100;
posy[i] = 50;
vx[i] = r(-MAX_VEL, MAX_VEL);
vy[i] = r(-MAX_VEL, MAX_VEL);
}
if (abs(vx[i]) > MAX_VEL) {
printf("Weird value (%d) for vx[%d]\n" f vx[i], i);
vx [i] = r (-MAX__VEL, MAX_VEL) ;
}
posx[i] = posx[i] + vx[i];
if (posx[i] < 0) {
/* Bounce off the left wall */
posx[i] =0;
vx[i] = -vx[i];
} else if (posx[i] > Xmax - SQUARESIZE) {
/* Bounce off the right wall */
vx[i] = -vx[i];
posx[i] = posx[i] + vx[i];
}
posy[i] = posy[i] + vy[i];
if (posy[i] > Ymax - SQUARESIZE) {
/* Bounce off the top */
posy[i] = Ymax - SQUARESIZE;
vy[i] = -vy[i];
} else if (posy[i] < 0) {
W sun
\r microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs ( animatecolor ) 451
/* Bounce off the bottom */
posy[i] *= 0;
vy[i] = -vy[i];
}
/* draw the square you can't see */
pw_rop(pw, posx[i] f posy[i], SQUARESIZE, SQUARESIZE,
PIX_SRC | PIX_C0L0R (usecolor (i + 1) ) , NULL, 0, 0) ;
}
/*
* swap the colormaps, and hey presto! should appear smoothly
*/
doublebuff_swap(Scolorstuff);
times_drawn++;
/* set the plane mask to be that which we are not viewing */
pw_j?utattributes (pw, (colorstuff. cur_buff == 1) ?
&(colorstuff.enable_l_mask): &(colorstuff.enable_0_mask));
/* erase now invisible planes */
for (i - 0; i < NUMBER; i++) {
if (times__drawn >1) {
/* squares have been drawn before */
/* erase in the one you can't see */
pw_rop(pw, prevpo sx[i], prevpo sy[i],
SQUARESIZE, SQUARESIZE, PIX__CLR, NULL, 0, 0) ;
}
/* remember so can erase later */
prevposx[i] = posx[i];
prevposy[i] = posy[i];
}
/*
* set the plane mask to be that which we are viewing, in
* case screen has to be repaired between now an when we are
* called again.
*/
pw_putattributes(pw, (colorstuff.cur_buff == 1) ?
& (colorstuff. enable_0_mask) : & (colorstuff. enable__l__mask)) ;
}
/* random number calculator */
int
r(minr, maxr)
int
minr
{
int
i;
i * random () % (maxr - minr + 1);
if (i < 0)
return (i + maxr + 1);
else
return (i + minr);
}
w sun
\T microsystems
Revision A, of May 9,1988
452 SunView 1 Programmer’s Guide
/* ARGSUNUSED */
static void
resize_j>roc(canvas, width, height)
{
times_drawn = 0;
/* remember, pixels start at 0, not 1, in the pixwin */
Xmax = width - 1;
Ymax = height - 1;
}
/*
* Do double buffering by changing the write enable planes and
* the color maps. The application draws into a buffer which is
* not visible and when the buffers are swapped the invisible one
* become visible and the other become invis.
*
* Start out drawing into buffer 1 which is the low-order buffer;
* ie. the low-order planes. Things would not work if this is not
* done because the devices start out be drawing with color 1
* which will only hit the low-order planes.
*
* Init double buffering: Allocate color maps for both buffers. Fill
* in color maps.
*/
doublebuff_init(colorstuff)
struct colorstuff ^colorstuff;
{
/*
* user has defined desired colors. Set them up in the two
* colormap
segments
*/
int
index__l ;
int
index__2;
int
i;
char
cmsname [CMS_NAMESIZE] ;
/* name colormap something unique */
sprintf (cmsname, ,, animatecolor%D", getpid()) ;
pw_setcmsname (pw, cmsname);
/*
* for each index in each color table, figure out how it maps
* into the original color table.
*/
for (i =0; i < colorstuff->cms_size; i++) {
/*
* first colormap will show color X whenever low order
* bits of color index are X
*/
index__l = i & ( (1 « colorstuff->colorbits) - 1);
/*
* second colormap will show color X whenever high order
* bits of color index are X
*/
index 2 = i » colorstuff->colorbits;
m sun
Xr microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs ( animatecolor ) 453
colorstuff->red[0][i] = colorstuff->redcolors[index_l];
colorstuff->green[0][i] = colorstuff->greencolors[index_l];
colorstuff->blue[0][i] = colorstuff->bluecolors[index_l];
colorstuff->red[l][i] = colorstuff->redcolors[index_2];
colorstuff->green[1][i] = colorstuff->greencolors[index_2];
colorstuff->blue[1][i] = colorstuff->bluecolors[index_2];
}
colorstuf f->enable__l__mask = ( (1 « colorstuff->colorbits) - 1)
« colorstuff->colorbits;
colorstuff->enable__0_mask = ((1 « colorstuff->colorbits) - 1);
/*
* doublebuff_swap sets up the colormap. We want the drawing
* to start off drawing into the 1st buffer, so set the
* current buffer to 1 so that when doublebuff_swap is called
* it will set up the first ([0] ) colormap.
*/
colorstuf f->cur__buff == 1;
doublebuf f__swap (colorstuff) ;
* Routine to swap buffers by loading a color map that will show
* the contents of the buffer that was not visible. Also, set the
* write enable plane so that future writes will only effect the
* planes which are not visible.
*/
doublebuff_swap(colorstuff)
struct colorstuff *colorstuff;
{
if (colorstuff->cur_buff == 0) {
/* display first buffer while writing to 2nd */
/*
* Careful! pw_jputcolormap () wants an array or pointer
* passed, but the colormap arrays are 2-d
*/
pw_j?utcolormap(pw, 0, colorstuff->cms_size,
colorstuff->red[0],
colorstuff->green[0],
colorstuff->blue[0]);
/* set plane mask to write to second buffer */
colorstuff->plane_mask = colorstuff->enable_l_mask;
colorstuff->cur_buff = 1;
} else {
/* display second buffer while writing to first */
pw_jputcolormap(pw, 0, colorstuff->cms_size,
colorstuff->red[1],
colorstuff->green[1],
colorstuff->blue[1]);
/* set plane mask to write to first buffer */
colorstuff->plane_mask = colorstuff->enable_0_mask;
colorstuff->cur_buff = 0;
}
}
Xr microsystems
Revision A, of May 9, 1988
454 SunView 1 Programmer’s Guide
A.10. Two gfx
subwindow-based
programs converted
to use SunView
The following two programs are the Sun demo programs bouncedemo and
spheresdemo converted from using gf xsw_init () to canvases in SunView.
The code for the SunWindows-based programs is in
/usr / share/src/sun/suntool so you can contrast that code with the
SunView versions printed here.
Techniques used to convert programs such as these to SunView 1 are described
in Appendix C, Converting SunWindows Programs to SunView.
bounce The first program is bouncedemo converted to draw in a canvas and to call
notif y_dispatch () periodically. Like the original bouncedemo, it restarts
drawing after any damage (if not retained) or resizing.
microsystems
Revision A, of May 9,1988
Appendix A — Example Programs {bounce) 455
#ifndef lint
static char sccsid[] = "@(#)bounce.c 1.5 88/02/26 Copyr 1986 Sun Micro";
#endif
/*
* Overview: Bouncing ball demo in window.
* Converted to use SunView by simulating the gfxsubwindow structure.
*/
/* this replaces all includes */
#include <suntool/sunview.h>
#include <suntool/canvas.h>
/* straight from the Canvas chapter */
static void repaint_proc();
static void resize_proc();
/* straight from the Notifier chapter */
static Notify_value my_notice_destroy();
extern Notify_error notify_dispatch();
static int
my_done;
/* define my own gfxsubwindow struct */
struct gfxsubwindow {
int
#define GFX_RESTART
#define GFX_DAMAGED
int
struct pixwin
struct rect
gfx_flags;
0x01
0x02
gfx_reps;
*gfx_pixwin;
gfx_rect;
}
mygfx;
struct gfxsubwindow *gfx = &mygfx;
W sun
\r microsystems
Revision A, of May 9, 1988
456 SunView 1 Programmer’s Guide
main(argc, argv)
int
char
argc;
*argv;
short x, y, vx, vy, z, ylastcount, ylast;
short Xmax, Ymax, size;
/* WIN_RECT attribute returns a pointer */
Rect *rect;
/* have to handle this arg that gfxsw_init used to process */
int retained;
/*
* replace this call if (gfx == (struct gfxsubwindow *)0) exit(l);
* with ...
*/
Frame
Canvas
Pixwin
frame;
canvas;
*pw;
/* this arg was also dealt with by gfxsw_init */
gfx->gfx_reps = 200000;
frame = window_create(NULL, FRAME,
FRAME_LABEL, "bounce",
FRAME_ARGC_P TR_ARGV, &argc, argv,
WIN_ERR0R_MSG, "Can't create frame",
0 );
for (—argc, ++argv; *argv; argv++) {
/*
* handle the arguments that gfxsw_init (0, argv) used to do
* for you
*/
if (strcmp(*argv, "-r") == 0)
retained =1;
if (strcmp(*argv, "-n") == 0)
if (argc > 1) {
(void) sscanf(*(++argv), "%hD", &gfx->gfx_reps);
argc++;
}
}
canvas = window_create(frame, CANVAS,
CANVAS_RETAINED, retained,
CANVAS__RE SIZ E_P ROC, resize_jproc,
CANVAS_FA S T_M0N 0, TRUE,
WIN_ERROR_MSG, "Can't create canvas",
0 );
/* only need to define a repaint proc if not retained */
if (!retained) {
window_set(canvas,
CANVAS_REPAINT_PROC, repaint_proc,
0 );
}
pw = canvas_pixwin(canvas);
m sun
Xr microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs ( bounce ) 457
gfx->gfx_jpixwin = canvas_pixwin(canvas);
/* Interpose my proc so I know that the tool is going away. */
(void) notify_interpose_destroy_func(frame, my__notice_destroy) ;
/*
* Note: instead of window_main_loop, just show the frame. The
* drawing loop is in control, not the notifier.
*/
window_set (frame, WIN_SHOW, TRUE, 0);
W sun
\r microsystems
Revision A, of May 9, 1988
458 SunView 1 Programmer’s Guide
Restart:
rect = (Rect *) window_get(canvas, WIN_RECT);
Xmax = rect_right(rect);
Ymax = rect__bottom(rect) ;
if (Xmax < Ymax)
size = Xmax / 29 + 1;
else
size = Ymax / 29 + 1;
/*
* the following were always 0 in a gfx subwindow (bouncedemo
* is confused on this point
*/
x = 0;
y = 0;
vx = 4;
vy = 0;
ylast = 0;
ylastcount = 0;
pw_writebackground(pw, 0, 0, rect->r_width, rect->r__height,
PIX_SRC);
/*
* Call notify_dispatch() to dispatch events to the frame
* regularly. This will call my resize and repaint procs and
* interposed notify_destroy__func if necessary. The latter will
* set my__done to TRUE if it's time to finish.
*/
while (gfx->gfx_reps) {
(void) notify_dispatch();
if (my_done)
break;
/*
* this program is not concerned with damage, because either
* the canvas repairs the damage (if retained) or it just
* restarts, which is handled by GFX_RESTART
*/
/*
* if (gfx->gfx_flags&GFX__DAMAGED) gfxsw_handlesigwinch(gfx);
*/
if (gfx->gfx__flags & GFX_RESTART) {
gfx->gfx_flags &= ~ GFX_RESTART;
goto Restart;
}
if (y == ylast) {
if (ylastcount++ > 5)
goto Reset;
} else {
ylast = y;
ylastcount =0;
}
pw_writebackground(pw, x, y, size, size,
PIX__N0T (PIX_DST) ) ;
x = x + vx;
if (x > (Xmax - size)) {
s /*
* Bounce off the right edge
*/
x = 2 * (Xmax - size) - x;
m sun
XT microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs (bounce) 459
r
vx = -vx;
} else if (x < 0) {
/*
* bounce off the left edge
*/
x = -x;
vx = -vx;
}
vy = vy + 1;
y - Y + vy;
if (y >= (Ymax - size)) {
/*
* bounce off the bottom edge
*/
y = Ymax - size;
if (vy < size)
vy = 1 - vy;
else
vy = vy / size - vy,
if (vy == 0)
goto Reset;
}
for (z = 0; z <= 1000; z++) ;
continue;
Reset:
if (—gfx->gfx_reps <= 0)
break;
x = 0;
y = 0;
vx = 4;
vy = 0;
ylast =0;
ylastcount = 0;
}
V.
m sun
\r microsystems
Revision A, of May 9, 1988
460 SunView 1 Programmer’s Guide
static void
repaint_proc( /* Ignore args */ )
{
/* if repainting is required, just restart */
gfx->gfx_flags |= GFX_RESTART;
}
static void
resize_proc( /* Ignore args */ )
{
gfx->gfx__flags |= GFX_RESTART;
}
/* this is straight from the Notifier chapter */
static Notify_value
my_notice_destroy(frame, status)
Frame frame;
Destroy_status status;
{
if (status != DESTROY_CHECKING) {
/* set my flag so that I terminate my loop soon */
my_done = 1;
/* Stop the notifier if blocked on read or select */
(void) notify_stop();
}
/* Let frame get destroy event */
return (notify_next_destroy_func(frame, status));
}
#sun
Xr microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs {spheres) 461
spheres This is an example of a program that has been converted to use
window_main_loop (). It displays a fixed-sized image in a canvas that has
scrollbars. It continues drawing its image when its window is damaged or
resized. However, it stops drawing when it is iconic.
You will have to create your own icon for this called spheres . icon.
microsystems
Revision A, of May 9, 1988
462 SunView 1 Programmer’s Guide
#ifndef lint
static char sccsid[] = (#)spheres.c 1.4 88/02/05 Copyr 1986 Sun Micro";
#endif
/*
* spheres — draw a bunch of shaded spheres Algorithm was done
* by Tom Duff, Lucasfilm Ltd., 1982
* Revised to use SunView canvas instead of gfxsw.
*/
#include <suntool/sunview.h>
♦include <suntool/canvas.h>
♦include <suntool/scrollbar.h>
♦include <sunwindow/cms_rainbow.h>
static Notify_value my_frame_interposer();
static Notify_value my_animation();
static void sphere();
static void demoflushbuf();
♦define ITIMER NULL
/*
* (NX, NY, NZ) is the light source vector
* 100
*/
♦define NX 48
♦define NY -36
♦define NZ 80
((struct itimerval *)0)
length should be
♦define BUF BITWIDTH
16
static struct pixrect *mpr;
static int
static int
static int
static Frame
static Canvas
static int
static Pixwin
width;
height;
counter;
frame;
canvas;
cmssize;
*pw;
static short spheres_image[256] = {
♦include "spheres.icon"
};
mpr_static(spheres_pixrect, 64, 64, 1, spheres_image);
main(argc, argv)
int
char
{
char
int
Icon
argc;
**argv;
**args;
usefullgray = 0;
icon;
icon = icon_create(ICON_IMAGE, &spheres_j>ixrect, 0);
frame * window_create(NULL, FRAME,
FRAME LABEL, "spheres".
sun
microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs (. spheres ) 463
FRAME_ICON, icon,
FRAME_ARGC_PTR_ARGV, & a r g c, argv,
0);
canvas = window_create(frame, CANVAS,
CANVAS_AUTO_EXPAND, 0,
CANVAS_AUTO_SHRINK, 0,
CANVAS_AUTO_CLEAR, 0,
/*
* Set SCROLL_LINE_HEIGHT to 1 so that clicking LEFT or RIGHT
* in the scroll buttons scrolls the canvas by one pixel.
*/
WI N_VERT I CAL_S CROLLBAR, scrollbar__create (S CROLL_L I NE_HE I GHT, 1,
0),
WIN_HORIZONTAL_SCROLLBAR, scrollbar_create(SCR0LL_LINE_HEIGHT, 1,
0),
0);
for (args = argv; *args; args++) {
if (strcmp(*args, "-g") == 0)
usefullgray =1;
}
/* Interpose in front of the frame's client event handler */
(void) notify_interpose_event_func(frame, my_frame_interposer,
NOTIFY_SAFE);
(void) notify_set_itimer_func(frame, my_animation,
ITIMER_REAL, &NOTIFY_POLLING_ITIMER, ITIMER_NULL);
width = (int) window_get(canvas, CANVAS__WIDTH) ;
height = (int) window_get (canvas, CANVAS_HEIGHT) ;
pw = canvas_j?ixwin (canvas) ;
cmssize = (usefullgray) ? setupfullgraycolormap(pw) :
setuprainbowcolormap(pw);
mpr = mem_create(BUF_BITWIDTH, height, pw->pw_j?ixrect->pr_depth);
window_main_loop(frame);
exit(0);
}
static int
static int
static int
static int
static int
static int
static int
static int
static int
/* ARGSUSED */
static
my__animation (client, itimer_type)
Notify_client client;
int itimer_type;
{
register i;
if (x >= radius) {
radius = r(0, min(width / 2, height / 2));
xO = r(0, width);
yO *= r(0, height);
radius;
xO; /* x center */
y0; /* y center */
color;
x;
y;
maxy;
mark;
xbuf;
Notify_value
® sun
XT microsystems
Revision A, of May 9, 1988
464 SunView 1 Programmer’s Guide
color = r(0, cmssize + counter++) % cmssize;
x = -radius;
xbuf = 0;
/*
* Don't use background colored sphere.
*/
if (color == 0)
color++;
/*
* Don't use tiny sphere.
*/
if (radius < 8)
radius = 8;
}
for (i =0; i < 5; i++) {
xbuf++;
maxy = sqroot(radius * radius - x * x) ;
pw_vector(pw, xO + x f yO - maxy, xO + x, yO + maxy,
PIX_CLR, 0);
for (y = -maxy; y <= maxy; y++) {
mark = r(0, radius * 100) <= NX * x + NY * y
+ NZ * sqroot(radius * radius -x*x-y*y);
if (mark)
pr_put(mpr, xbuf, y + yO, color);
}
if (xbuf == (mpr->pr_width - 1)) {
demoflushbuf(mpr, PIX_SRC | PIX_DST,
x + xO - mpr->pr_width, pw);
xbuf = 0;
x++;
return (NOTIFY_DONE);
}
x++;
}
if (x >= radius)
demoflushbuf(mpr, PIX_SRC | PIX_DST, x + xO - (xbuf + 2),
pw) ;
return (N0TIFY_D0NE);
static void
demoflushbuf(mpr, op, x, pixwin)
struct pixrect *mpr;
int op;
int x;
struct pixwin *pixwin;
{
register u_char *sptr, *end;
sptr = mprd8_addr (mpr__d (mpr) , 0, 0, mpr->pr_depth) ;
end = mprd8_addr(mpr_d(mpr), mpr->pr_width - 1,
mpr->pr_height - 1, mpr->pr_depth);
/*
* Flush the mpr to the pixwin.
*/
pw_write(pixwin, x, 0, mpr->pr_width, mpr->pr__height, op.
m sun
Xr microsystems
Revision A, of May 9, 1988
Appendix A — Example Programs (spheres) 465
mpr, 0, 0);
/*
* Clear mpr with 0's
*/
while (sptr <= end)
*sptr++ = 0;
/* Let user interact with tool */
notify_dispatch () ;
}
static int
setuprainbowcolormap(pw)
Pixwin *pw;
{
register u_char red[CMS_RAINBOWSIZE];
register u_char green[CMS_RAINBOWSIZE];
register u_char blue[CMS_RAINBOWSIZE];
/*
* Initialize to rainbow cms.
*/
pw_setcmsname(pw, CMS_RAINBOW);
cms_rainbowsetup(red, green, blue);
pw_putcolormap(pw, 0, CMS_RAINBOWSIZE, red, green, blue);
return (CMS_RAINBOWSIZE);
}
static int
setupfullgraycolormap(pw)
Pixwin *pw;
{
#define CMS_FULLGRAYSIZE 256
#define CMS_FULLGRAY "fullgray"
register u_char red[CMS__FULLGRAYSIZE] ;
register u_char green [CMS__FULLGRAYSIZE] ;
register u_char blue[CMS_FULLGRAYSIZE];
register i;
/*
* Initialize to rainbow cms.
*/
pw_setcmsname(pw, CMS_FULLGRAY);
for (i = 0; i < CMS_FULLGRAYSIZE; i++) {
red[i] = green[i] = blue[i] = i;
}
pw_putcolormap(pw, 0, CMS_FULLGRAYSIZE, red, green, blue);
return (CMS_FULLGRAYSIZE);
}
static Notify_value
my_frame__interposer (frame, event, arg, type)
Frame frame;
Event *event;
Notify_arg arg;
Notify_event_type type;
{
m sun
Xr microsystems
Revision A, of May 9, 1988
466 SunView 1 Programmer’s Guide
r
int
Notify_value
closed_initial, closed_current;
value;
/* Determine initial state of frame */
closed_initial = (int) window__get (frame, FRAME_CLOSED) ;
/* Let frame operate on the event */
value = notify_next_event_func(frame, event, arg, type);
/* Determine current state of frame */
closed_current = (int) window_get(frame, FRAME_CLOSED) ;
/* Change animation if states differ */
if (closed_initial != closed_current) {
if (closed_current) {
/* Turn off animation because closed */
(void) notify_set_itimer_func (frame, my__animation.
ITIMER_REAL, ITIMER_NULL, ITIMER_NULL)
} else {
/* Turn on animation because opened */
(void) notify_set__itimer_func (frame, my__animation,
ITI MER__REAL, &NOTIFY_POLLING_ITIMER,
ITIMER_NULL);
return (value);
}
Revision A, of May 9, 1988
B
Sun User Interface Conventions
Sun User Interface Conventions. 469
B.l. Program Names. 469
B. 2 . Frame Headers. 469
B. 3 . Menus. 469
Capitalization. 469
Menus Showing Button Modifiers. 470
Interaction with Standard Menus. 470
Enable/Disable Menu Items. 470
Multi-Column Menus. 470
B. 4 . Panels. 470
Buttons. 471
List of Non-Exclusive Choices. 471
List of Exclusive Choices. 471
Binary Choices. 472
Text Items . 472
Allocation of Function Between Buttons and Menus. 472
B. 5 . Mouse Button Usage. 473
Allocation of Function Between Mouse Buttons . 473
Using Mouse Buttons for Accelerators. 473
B.6. Cursors. 473
B.7. Icons. 473
#
Sun User Interface Conventions
B.l. Program Names
B.2. Frame Headers
The window programs released by Sun follow some standard user interface con¬
ventions. These conventions are described here so that, if you choose, you can
design your interfaces with them in mind.
Here are some guidelines for naming programs:
□ A window-based version of an existing tty-based program has tool appended
to the end of the existing program. For example mailtool is a window-
based version of the tty-based program mail(l).
□ A program without a tty version should not end with tool. Thus the icon edi¬
tor is called iconedit and not icontool.
□ Since tools are normally invoked from command files or menus, descriptive
names are better than short cryptic ones. Thus iconedit is better than ied.
The frame header should contain the name of the program, optionally followed
by a dash and additional information, as in:
textedit - /tmp/file, dir: /usr/dg/doc
I I
B.3. Menus
Capitalization The words in menus should be capitalized as they would be in a chapter heading:
Close
Move ><►
Resize =»
Expose
Hide
Redisplay
Quit
This convention can be bent when the names in the menu correspond to already
existing, non-capitalized command names.
469
microsystems
Revision A, of May 9, 1988
470 SunView 1 Programmer’s Guide
Menus Showing Button
Modifiers
Interaction with Standard
Menus
Enable/Disable Menu Items
Multi-Column Menus
B. 4 . Panels
When the behavior of a panel button depends on whether the user holds down a
shift key, the button should have a menu summarizing the different actions, as in
this menu from the Reply button in mail tool:
reply
Reply (all)
[Shift]
reply, include
[Ctrl]
Reply (all). Include
[Ctrl][Shi ft]
Standard SunView menus, such as the frame menu, should not be modified.
When a user is used to seeing ‘Quit’ at the end of the frame menu, it is confusing
to see a frame menu with a new item tacked on at the end. Equally confusing is a
frame menu that comes up with an item other than ‘Close’ at the top. Thus,
instead of deleting an item from a standard menu, applications should render the
item inactive and “grayed-out.” And instead of adding a new item to a standard
menu, applications should make a new menu, with the name of the standard
menu at the top, followed by the application-specific commands. The standard
menu then becomes a pullright subordinate to the custom menu, as in the exam¬
ple below:
Frame
Close
Dump Sere
Move +
Dump Regi
Resize =*
Print Dum
Expose
View Dump
Hide
Redisplay
Quit
Sometimes a menu has two different states, with different words appearing in the
same position in a menu, depending on the current state. When the two states
correspond to something being on or off, the words ‘Enable’ and ‘Disable’
should be used. Thus shelltool uses ‘Enable Page Mode’ and ‘Disable Page
Mode’.
Overly long menus should be avoided. Use menus with more than one column
instead.
The defaults for panel items given in this section are intended to promote con¬
sistency across applications and provide convenient building blocks for program¬
mers who don’t want to put a great deal of effort into designing fancy panels.
The intent is not to rule out the use of non-default panel items.
Xr microsystems
Revision A, of May 9,1988
Appendix B — Sun User Interface Conventions 471
Buttons
List of Non-Exclusive Choices
List of Exclusive Choices
The proper use of buttons is to allow the user to initiate commands. Button items
should not be used to represent categories, modes or options — for these kinds of
choices that imply a change of state, you should use toggle, choice or cycle
items, as described in the next three sections.
When creating a button, use the routine panel_button_image () to create a
button-like image, as in:
{ Dump Screen"**^
As with menu entries, capitalize buttons unless the button name matches some¬
thing else (for example, dbx(l) commands in dbxtool). If the button’s mean¬
ing can be modified by I Control I or I Shift I these modifiers should be indicated in
the button’s menu. (For an example, see the picture of the Reply menu from
mail tool, at the top of the preceding page.)
In most cases, a button will remain visible all the time. However, when a tool
has different states, and a button can only be used in some of those states, it is
usually best to make the button invisible when it can not be invoked. Thus in
mailtool, the Cancel button only appears when a letter is being composed.
A list of choices in which more than one choice can be selected at a time is best
implemented with the item type PANEL_TOGGLE. The default for toggles is a
list of check boxes:
Optional Software:
E?' Database
□ Demos
^Document Preparation Tools
□ Games
0^Productivity Tools
The example shows a vertical list; vertical or horizontal are both acceptable.
A list of choices in which only one choice can be selected at a time can be
displayed with all choices visible or with only the current choice visible. To
show all the choices, use the item type PANEL_CH0ICE. The default for choice
items is a list of square pushbuttons, with the current choice marked by a dark¬
ened pushbutton:
Drawing Mode: a Point a Line a Rectangle a Circle a Text
To show only the current choice, use PANEL_CYCLE. This item type provides a
symbol consisting of two circular arrows, which indicate to the user that he can
cycle through choices, and serves to distinguish cycle items from text items:
Category OsunView
Asun
XT microsystems
Revision A, of May 9,1988
472 SunView 1 Programmer’s Guide
Binary Choices
An item that is either on or off may be created using either PANEL_TOGGLE,
PANEL_CYCLE or PANEL_CH 0 ICE. The picture on the left below is a toggle,
the two in the middle are cycles, and the one on the right is a choice:
O' Grid Show Grid O Yes Grid O On Grid: B On Q Off
Text Items
Text items should have a colon after the label.
For text items, it is recommended to have one or more buttons which cause the
text item’s value to be acted on. In iconedit, for example, the user first enters
a filename into the File: field, then presses the Load, Store, or Browse button in
order to act on that filename.
iconedit also allows the user to tvpe I Control-L 1.1 Control-S ). or (Control-B 1
into the File: field as accelerators for the buttons. Use of such accelerators
(including carriage return to mean “enter”) is not recommended, as it conflicts
with future plans for the use of non-printable characters.
For the sake of consistency, whenever a tool reads from and writes to a file, it
should label these buttons with Load and Store.
Allocation of Function
Between Buttons and Menus
Selecting a menu item is normally the same as either selecting a button or pick¬
ing from a choice item, bogglet ool(6), for example, has a menu for restart¬
ing the game (as well as other things) but has no buttons. Each of the four menu
items could have been represented by a button instead, lif e(6) does not have a
choice item, but rather lets you choose a starting pattern with a menu. Thus the
question of when to use a button (or choice) and when to use a menu arises. Here
are some rules of thumb:
□ Items on the frame menu should not be duplicated as buttons, with the possi¬
ble exception of a Quit button (see next paragraph).
□ Some tools typically run all the time, such as mailtool. Others are nor¬
mally invoked only long enough to do a job, such as iconedit. Tools in
the second category, if they have any other buttons, should also have a Quit
button.
□ If a tool has a commit operation, then it may have a Done button, which is a
combination of close 106 plus commit. Thus mailtool has a Done button.
□ A tool should never have a Close button, since this operation is already
available via both a menu and the keyboard.
□ If a custom menu is provided, the menu items should not all be duplicated as
panel items (buttons or choices), bogglet ool and lif e are examples of
programs that have functionality in custom menus that are not duplicated as
panel items.
□ When a button and a menu item perform the same function, their labels
should be identical.
106 If the panel is in a subframe, the Done operation implies disappearing from the screen rather than
closing, since subframes can’t become iconic.
microsystems
Revision A, of May 9, 1988
Appendix B — Sun User Interface Conventions 473
B.5. Mouse Button Usage
Allocation of Function
Between Mouse Buttons
Use of mouse buttons should be consistent with the rest of SunView. The left
button should only be used to make selections. The right button should only be
used to bring up menus. 107
There is some discretion involved in the use of the middle button, however. In
most of SunView, the middle button is used to adjust a selection. In text and
shell windows, for example, the left button is used to mark the starting point of a
selection, and the middle button is used to extend the selection. Similarly, in a
pixel editor that allowed you to select regions, clicking the left button on a region
could select just that region, and clicking the middle button on another region
could add that region to the selection. On the other hand, in a tool that allowed
you to move objects, the middle button could move an object, and
(Control l-MIDDLE button could re-size it, which would be consistent with the
way icons and frames are moved and re-sized. As a third alternative, in the
iconedit drawing program the left button draws pixels (which is a kind of
selecting) and the middle button erases.
The best use of the middle button is still being discussed. Future versions of this
guideline may specify more exactly how the middle button should be used. For
now, the most common use is to extend the selection, and the next-most common
is to move a graphic object.
Using Mouse Buttons for
Accelerators
It is acceptable to use the mouse buttons as accelerators for common operations.
The only caveat is that any accelerators should also be available from a menu or
panel item. Thus in SunView clicking on a tool with the middle button moves
the tool, but you can also move a tool using the frame menu.
Some operations, on the other hand, cannot be invoked from a menu or panel
button. In such cases the mouse is the only means of invoking the operation. For
example, in iconedit you use the mouse for drawing, and the drawing opera¬
tions are not available from a menu or button.
B.6. Cursors
An application program should not do anything other than change the shape of
the cursor when the cursor is moved into a new window, text edit presents a
good example of using the cursor to alert the user that input is interpreted dif¬
ferently in different regions: The cursor is a thin diagonal arrow in the
textsubwindow, a fat horizontal arrow in the scrollbar, and a diamond in the
scrollbar buttons.
B.7. Icons
Tools should pack as much information as possible into their icons, clock and
perf meter are examples of tools that make good use of icon real estate, tex-
t edit is an example of a tool that could make better use of its icon. For exam¬
ple, it could contain a representation of the text being editing in a 1 point font.
Small as that is, you can tell at a glance if you are editing C code or a mail mes¬
sage.
107 People who want to hold the mouse with their left hand can put the “menu button** on the left and the
“select button** on the right by setting the Left_Handed option in the Input category of def ault sedit.
®sun
xr microsystems
Revision A, of May 9, 1988
474 SunView 1 Programmer’s Guide
Some icons, like the round face used by clock and the page with the protruding
pencil used by text edit, have images with non-square outlines. These icons
have the area outside of the image outline filled in with the root grey pattern so
that the icons will blend in with the default SunView background. While this
looks good when the background is in fact the default pattern, it is not recom¬
mended, since users can choose an arbitrary background pattern for SunView.
Revision A, of May 9,1988
Converting SunWindows Programs to
Sun View
Converting SunWindows Programs to Sun View.. 477
C.l. Converting Tools. 478
General Comments . 478
Programming Style Changes. 478
Object typedefs. 478
Attribute Value Interface. 478
New Objects. 479
Canvas Subwindows. 479
Text Subwindows. 479
Scrollbars. 479
Objects in Common between SunView and SunWindows. 480
Cursors. 480
Icons. 480
Menus... • . 481
Input Events. 481
Setting up Input Event Handling. 482
Sigwinch Handling. 482
Windows. 482
Panels. 482
Signals . 483
Prompts. 483
C. 2 . Converting Gfxsubwindow-Based Code. 485
Basic Steps. 485
Replacing Tool Interaction. 485
Styles of Damage Checking. 485
Either the Notifier Takes Over. 485
Or Your Code Stays in Control. 486
Handling Damage. 486
The gf xsw Structure. 486
Finishing Up. 487
Miscellaneous. 487
Two Examples. 488
Converting SunWindows Programs to
Sun View
This appendix gives some guidelines for converting programs written using
SunWindows to SunView. There are two classes of programs covered: those
that create a tool and subwindows, and programs that call gf xsw_init () to
take over an existing window or the console.
Programs that fall outside these classes are probably UNIX-style programs that do
not use windows at all. The conversion of such programs is in effect the subject
of this whole manual. If you want to convert such a program to SunView, pay
particular attention to Chapter 2, The SunView Model, and the specific discussion
of Notifier interaction under Porting Programs to SunView in Chapter 17, The
Notifier. You may also find some of the discussion later on in this appendix
under Section C.2, Converting Gfxsubwindow-Based Code, helpful.
XT microsystems
477
Revision A, of May 9,1988
478 SunView 1 Programmer’s Guide
C.l. Converting Tools
It is reasonably straightforward to convert tools that create windows in SunWin-
dows to the SunView interface because they should already have the appropriate
architecture. SunView programs, like Sun Windows programs, have three parts:
initialization of static objects, starting up window system interaction, and the
routines that are called after the tool is running in the window system.
General Comments
When porting to SunView, you should look through all of your code for Sun Win¬
dows function calls. If you see one, the odds are that you are going to have oth¬
ers. Look for every occurrence of the call and then change it to the new format.
Since the SunView libraries are mixed in with the SunWindows libraries, you
can mix the two types of functions calls, and not get any compilation errors. But
you will get some inconsistent results.
Programming Style Changes
Object typedefs
The capitalized typedefs for window system objects (applied to Panels,
Panel_items and Panel_settings in 2.0 SunWindows) have been
extended to nearly all SunView objects, including:
Canvas Pixrect
Cursor Pixwin
Frame Rect
Icon Rectlist
Menu Scrollbar
Panel Textsw
Panel_item Tty
Pixfont Window
You should convert to using these data types in the interests of future compatibil¬
ity. See Object Handles in Chapter 3, Interface Outline, for more information on
these types.
Attribute Value Interface
In SunView, the attribute value interface, introduced for panel subwindows in 2.0
SunWindows, has been extended to all types of windows. Attributes for all win¬
dow types are set and obtained with the same two calls, window_set () and
window_get().
All window types are created with the same call, window_create ().
CAUTION
The most frequently used SunView calls use attribute lists, and therefore
must be null-terminated. SunView will only complain about a malformed
attribute list at run time.
Xr microsystems
Revision A, of May 9, 1988
Appendix C — Converting SunWindows Programs to SunView 479
New Objects
Canvas Subwindows
Text Sub windows
Scrollbars
Most of the data types in the above list are objects new in SunView. Many
objects in SunWindows correspond to objects in SunView, for example:
tool => Frame
ttysw => Tty
Some objects such as the graphics subwindow and empty subwindow are not
supported in SunView 108 . There are new objects that partially take their place.
The canvas subwindow is a general-purpose drawing subwindow, which can
replace gfx subwindows and empty subwindows. The size of the canvas you
draw on need not be the same as the size of the window it is displayed in; you
can create scrollbars to let the user adjust the visible part of the canvas. For a
demonstration of the various canvas attributes, run the program
/usr/demo/canvas_demo
These allow for the display and editing of text in a scrollable window. The user
can perform various actions on the text, including saving the text, searching in
the text, and editing the text without the programmer having to deal with these
interactions.
Since there was no such window in SunWindows, your application may have had
to use a gfx subwindow, a set of panel message items, or some strange technique
involving tty sw_input () or piping to a tty subwindow to display text; the
text subwindow can replace all these uses.
Scrollbars can be attached to windows. In particular, the use of scrollbars with
retained canvases makes it very easy to draw a fixed-size image without regard
for window size changes.
108 You can still compile and run code that uses these, but Sun does not intend to develop them further.
xr microsystems
Revision A, of May 9, 1988
480 SunView 1 Programmer’s Guide
Objects in Common between
SunView and Sun Windows
Cursors
Icons
Cursors have changed. They are now type Cursor, and all calls relating to
them have changed. Type Cursor should be looked at as a pointer to the struc¬
ture containing the cursor information. Here is how you would define a cursor:
--
static short int help_bits [] = {
tinclude "help.curs"
};
mpr_static(help_pr, 16, 16, 1, help_bits);
*_ J
Once having created a cursor, you call window_set () to add it to a window,
as in the following code fragment:
Cursor help_cursor;
main ()
{
/* make windows */
init cursor!);
init_cursor()
{
help_cursor = cursor_create(CURSOR_IMAGE, &help_pr,
CURSOR_XHOT, 8,
CURSOR_YHOT, 8,
CURSOR_OP, XOR,
0 ) ;
window_set (window, WIN_CURSOR, help_cursor, 0);
You now refer to all your cursors by the handle you get from
cursor_create (). Cursors have their own create, destroy, copy, set, and get
routines, as well as a number of attributes with no corresponding functionality in
SunWindows.
Icons have changed. They follow the same pattern as cursors; you define the
data, create a pixrect, and then call icon_create () at run time. These also
have their own create, destroy, set and get routines, although there are fewer attri¬
butes associated with them.
#sun
xr microsystems
Revision A, of May 9, 1988
Appendix C — Converting SunWindows Programs to Sun View 481
Menus
Input Events
The new walking menu package uses the attribute value interface. It has many
more features than the old menu package. It does not support the stacking menu
style of SunWindows. 109
Menus also have their own routines and are created via function calls instead of
being user-loaded data structures. They use the pointer type Menu for their han¬
dles instead of struct menuptr. One way to create them is to write a spe¬
cial menu_init () proc which loads them into their structures correctly. In
your menu_init (), you have something like
/
\
ml_items = menu_create(
MENU_STRI NG__I TEM,
"insert",
INSERT,
MENU_STRING_ITEM,
"copy",
COPY ,
MENU_STRING_ITEM,
"replace",
REPLACE,
MENU_STRING_ITEM,
"move" f
XLATE ,
MENU_STRING__I TEM,
"delete",
DELETE,
MENU_STRING_ITEM ,
"HELP",
DRAW_HELP,
0);
Menu values from menu_get () ormenu_show () are returned as
caddr_t’s. Be sure your types match.
NOTE The old menu_display () and the newmenu_show () routines have a dif¬
ferent order for the arguments.
The inputevent structure has not changed. However, you no longer have to
generate events yourself in “selectedroutines via calls to
input_readevent (). Instead, windows now have event handlers that are
passed pointers to Event structures.
There are a number of macros for making input events easier to deal with in Sun-
View, so instead of having something like ie->ie_code you have
event_id (ie), resulting in more readable code.
Event types are not pointers, so you have to distinguish between
Event *ie;
and
Event ie;
in your code. You can use either, because the event functions don’t just manipu¬
late a handle as, for example, the cursor functions do. See Object Handles in
Chapter 3, Interface Outline, for an explanation of when handles are pointers and
when not.
109 This is still available in the frame and root menus if you disable SunViewlWalking_Menus in
defaultsedit.
Revision A, of May 9, 1988
482 SunView 1 Programmer’s Guide
Setting up Input Event Handling All the input events can be set up from the window_create () call or
window_set () calls. Calls to win_*inputmask () are all replaced by
these window_set () and window_create () calls.
The distinction between “pick” and “keyboard” events is new in SunView, hav¬
ing been added to support the notion of a split input focus.
CAUTION Be careful that when you are setting mouse events, you are modifying the
WI N_*_P I CK_EVENT S and when you are setting keyboard events you
modify WlN_*_KEYBOARD_EVENTS. You may get inconsistent results if
you modify pick events on the keyboard mask.
Sigwinch Handling Canvas event procedures no longer need all the gfx support for flag checking.
Resize and repaint events are separately handled by the procedures you supply
via the CANVAS_RESlZE_PROC and CANVAS_REPAlNT_PROC attributes.
These procedures mean you should not try to catch sigwinch signals (and in fact,
if you do, you will have problems; see below).
Windows Making windows is very straightforward in SunView. Each window type has a
handle — so instead of the inconsistent use of handles and fd’s to describe a
window and manipulate it, you only use the window handle. You need to go
through your code and update all the reference to the old tool_... handle types
in the code. After you find them, locate all the function calls referring to them
and update them to SunView window_set () and window_get () calls.
Almost every window operation is supported by the attribute value interface;
however, some low-level routines that are documented in the SunView 1 System
Programmer’s Guide may still require window names or fd’s.
window_get () is used to get an attribute of a window. It returns a caddr_t
back to you, which must be cast into the appropriate type. So loading something
into a rect struct would involve something like:
\
Rect
win size;
Canvas
canvas;
canvas =
: window_create( base_frame, CANVAS , 0);
win_size
:= *((Rect *)window_get(canvas, WIN_RECT));
V_
NOTE Be sure to cast values returned from get () routines to the correct type.
The above * ( (Rect *)...) is needed otherwise you will get an ’incompatible
type’ message from the compiler.
Panels Most of the panel interface was already using an attribute value interface in 2.0
SunWindows. panel_create () panel_set () and panel_get () should
be changed to window_create (), window_set ( ) and window_get ().
The PANEL_CU () macro was superseded by ATTR_COL ( ) and
ATTR ROW().
Asun
microsystems
Revision A, of May 9, 1988
Appendix C — Converting SunWindows Programs to SunView 483
Signals
Prompts
If you are catching signals, then you should read the documentation on signals in
Section 17.2, Restrictions, in the Notifier chapter. There are several that the
Notifier now catches on your behalf.
You should no longer be catching SIGWINCH signals. If you do, your program
may never appear on the screen as it will start catching the signals and redrawing
endlessly on die screen, which may not be visible.
Instead of using the menu_prompt () facility of SunWindows, you should use
the alerts package to prompt the user, or if necessary use pop-up subframes and
window_loop (popup_f rame ) when prompting the user. The filer example
programs in Chapter 4, Windows, uses the alerts package to implement a pop-up
confirmer.
menu_prompt () is documented here for completeness. The definitions used
by menu_prompt () are:
struct prompt {
Rect prt_rect;
Pixfont *prt_font;
char *prt_text;
}
menu_prompt(prompt, event, windowfd)
struct prompt *prompt?
struct inputevent *event;
int windowfd;
menu_prompt () displays the string addressed by prompt->prt_t ext
using the font prompt->prt_f ont. prompt->prt_rect is relative to
windowfd. If either the r_width or the r_height fields of
prompt->prt_rect has the value PROMPT_FLEXlBLE, that dimension is
chosen to accommodate all the characters in prompt->prt_text.
The fullscreen access method is used to display the prompt. After displaying the
prompt, menu_prompt () waits for any input event other than mouse motion.
It then removes the prompt, and returns the event which caused the return in
event, windowfd is the file descriptor of the window from which input is
taken while the prompt is up.
microsystems
Revision A, of May 9, 1988
484 SunView 1 Programmer’s Guide
Table C-l SunWindows => SunView Equivalences
In SunWindows
In Sunview
tool = tool_make()
Frame frame = window_create (NULL, FRAME,..., 0);
t o o l_pa r s e__a 11
FRAME_ARGS or FRAME_ARGC_PTR_ARGV
attributes to window__create (NULL, FRAME, ..., 0)
tool__install ()
tool_select()
tool_destroy()
window_main_loop(frame);
or, individually,
tool_install ()
win_show attribute
tool_select ()
window_main_loop(), notify_dispatch ( ) or notify_start ()
tool_destroy ()
window_destroy (basef rame) or window_don e (any window)
signal (SIGWINCH, sigwinch)
resize_proc and repaint_proc attribute
TOOLSW_EXTENDTOEDGE
WIN_EXTEND_TO_EDGE
win grabioO
WI N_GRAB_AL L_I NPUT attribute
struct tool_io
win_event_proc for window events. Other events, timers, etc.
handled by individual calls to the Notifier to set up or interpose specific procs.
XT microsystems
Revision A, of May 9, 1988
Appendix C — Converting SunWindows Programs to SunView 485
C.2. Converting Programs that run in gfxsubwindows are designed to take over an existing win-
Gfxsubwindow-Based dow. In SunView you must create a tool for such programs to run in. One limi-
Code tation of this approach is that the SunView version of the application must run
under suntools; the old gf xsw_init () call would create a SunWindows
environment if run on the “bare” Sun console. One major advantage gained by
moving to SunView is that your code can use scrollbars.
Basic Steps
Replacing Tool Interaction
Styles of Damage Checking
o Include <suntool/sunview. h> and <suntool/canvas .h>.
□ Remove all window-related #include statements; these will probably be
included by sunview. h.
□ Declare a Frame and a Canvas.
□ Replace gf xsw_init () with calls to create the frame and canvas.
Many gfx subwindow programs (and many of the Sun demos) call
gf xsw_init () to take over a window, then run in a loop as they compute and
draw an image in the gfx subwindow. At some point in the loop they check for
damage to or alteration of the size of the gfx subwindow and handle it accord¬
ingly.
In SunView, the coexistence of your program with the window system is less
hidden from you. Read Chapter 2, The SunView Model, to understand how this
coexistence works. In converting programs, you must ensure the Notifier runs at
regular intervals so that window events such as close, quit, etc. are handled
appropriately.
Consult Chapter 17, The Notifier, for more information.
You can either (1) set up your program so that, after initialization, control passes
to the Notifier, which you have set up to call your imaging/computation routine
periodically, or (2) let control continue to pass to your code, and change the pro¬
gram to call the Notifier at regular intervals.
Either the Notifier Takes Over In the first case, you set up your imaging/computation routine as a function that
is called when a timer expires. Do this by calling
notif y_set_it imer_f unc (). If you want your imaging/computation rou¬
tine to blaze away non-stop (causing other programs to run more sluggishly), you
request the timer function be called as soon as the Notifier has handled window
events for you by giving the timer the special value
&NOTIFY_POLLING_ITIMER.
(void) notify_set_itimer_func(frame, my_animation,
ITIMER_REAL, &NOTIFY_POLLING_ITIMER, ITIMER_NULL) ;
V__ )
If your code sleep ()’s on a regular basis, then you should be able to modify it
so that the Notifier calls your imaging/computation routine at the same interval.
Asun
microsystems
Revision A, of May 9, 1988
486 SunView 1 Programmer’s Guide
The program spheres in Appendix A, Example Programs, is an example of this
style of interaction.
Or Your Code Stays in Control
On the other hand, if your program just loops, perhaps while (—gf x_reps),
then you could add to the loop a call to notif y_dispatch (). This will han¬
dle window system events and return.
The program bounce in Appendix A, Example Programs, is an example of this
style of interaction.
If you do this then your program has to detect when the user has ‘Quit’ from the
menu: see Finishing Up below.
NOTE
gf x_reps in a gfx subwindow program is set to a large number (200,000), but
the user can change it through the command line argument
-n numberofrepetitions.
Handling Damage
The Notifier will handle moving the window, resizing it, etc. However, resulting
damage to your canvas may need to be repaired. In the gfx subwindow,
GFX_DAMAGED is set whenever a SIGWINCH is received. In addition
GFX_RESTART is set if the size of the window has changed or if the window is
not retained. GFX_DAMAGED is set as a hint for you to call
gf xsw_handlesigwinch (), which would clear up the damaged list and if
the window was retained it would repaint the image for you. GFX_RES TART is
set as a hint that the window had to be rebuilt, either because of damage and the
window is not retained, or because of a resize.
Many situations that you would need to handle yourself in a gfx subwindow are
rendered superfluous by attributes of the canvas subwindow, such as
CANVAS_AUTO_CLEAR, etc. For starters, canvases are retained by default; if
your canvas has scrollbars and is retained, then you need not be concerned with
resize events. Nevertheless, you may need to be aware when you must rebuild or
repair your image. Read the Canvases chapter for more information.
Rather than setting a flag, SunView calls your own procedure if you specify one
with the CANVAS_REPAINT_PROC and CANVAS_RES IZE_PROC attributes.
These are called with useful parameters for their tasks.
You can modify your code so that the repair activity that used to take place after
noticing the flags have been set now takes place in the procs themselves, or you
can write the procs so they set flags similar to the GFX_RE START and
GFX_REPAINT flags and return, and leave your repair code almost untouched.
Or, depending on your application, you can set up your canvas so that the win¬
dow system handles all damage.
The gfxsw Structure
The gfxsw structure has fields in it that carry useful information. Comparable
information is available in SunView, so you can declare and setup a comparable
structure in SunView. The bounce program in Appendix A, Example Programs,
does this.
Gfx subwindow-based programs use the gf x->gf xsw_rect to determine the
geometry of the window they are drawing in. Since the starting point of this was
XT microsystems
Revision A, of May 9, 1988
Appendix C — Converting SunWindows Programs to SunView 487
Finishing Up
Miscellaneous
relative to the gfxsw, it was always O. 110 In SunView the width and height of the
canvas you draw in are available through the canvas attributes CANVAS_WIDTH
and CANVAS_HEIGHT. The fields of the gf x->gfxsw_rect correspond to
these attributes as follows:
coord r_left, r_top; are both = 0
short r_width, r_height; are the CANVAS_WIDTH and
CANVAS_HEIGHT attributes.
As described above, you can use your own GFX_RESTART and GFX_REPAINT
flags.
If you care about the gfxsw command line arguments, insert code into your
program’s argv, argc parsing loop to handle the gfx options that used to be
taken care of for you. The bounce program has reasonable code to do this.
If your imaging routine is in control and periodically calls the Notifier, then when
the window is quit your routine must know that this has occurred. Otherwise, the
imaging routine will continue to draw in a window that has been destroyed, and
you will see error messages like
(~ ; : : - : ' —— " - ~~ i
WIN ioctl number C0146720: Bad file number
_____ : ____ J
until you kill the program.
What you must do is interpose in front of the frame’s destroy event handler so
that your program will know when the frame goes away. See the item on Getting
Out in Porting Programs to SunView in the Notifier chapter.
If your program exits on its own, then it can call window_done () to destroy
its windows. This will invoke your interposed notice-destroy routine (which may
or may not matter depending on what it does). It will also call the standard
Are you sure you want to Quit?
alert unless you set FRAME_NO_CONFIRM.
gf xsw_getretained () is equivalent to the CANVAS_RETAINED attribute.
Canvases are retained by default.
gf xsw_init () doesn’t consume the gfxsw command line options -r,
-n Number_of repetitions, etc; your code may do strange things with its argu¬
ments to deal with this.
no
Many of the demos supplied by Sun are confused on this point and go through unnecessary steps.
microsystems
Revision A, of May 9, 1988
488 SunView 1 Programmer’s Guide
Two Examples Listings of two programs converted from SunView are in Appendix A, Example
Programs.
bounce The first is a new version of bouncedemo(6). It now draws its bouncing square
in a canvas. It has code to parse the standard gfx subwindow command line
arguments. It preserves the original while (gfx->gfx_reps) {...} loop
structure of bouncedemo by calling not i fy_di spat ch () at the top of the
loop. Because it is running in a loop it must detect when the user has ‘Quit’ the
window, so it interposes before its frame’s destroy routine using
not if y_interpose_destroy_f unc (). The routine that is called just
sets a flag so the program knows to exit from the loop.
spheres The second is a version of spheresdemo(6). It now draws its shaded spheres
in a canvas with scrollbars, so you can see all the image in a small window. It
handles the notification of SunView events by asking the Notifier to call the
drawing routine (my_animation ()) as often as possible, using
. — ---.
(void) notify_set_itimer_func(frame, my_animation,
ITIMERJREAL, & NOTIFY_POLLING_ITIMER, ITIMER_NULL);
\_ j
Since the drawing operation is under the control of the Notifier, the Notifier can
control the program, so the while (gfx->gfx_reps) {...} loop structure
is replaced by a call to window_main_loop (); this will terminate the pro¬
gram when the user chooses ‘Quit’ from the frame menu.
spheres detects when it is made iconic by interposing in front of the frame’s
client event handler using not if y_interpose_event_func (). The rou¬
tine that is called calls the normal event_f unc, then checks to see if the frame
has changed state: if it has been closed it turns the notify timer off altogether, so
the drawing routine is no longer called; if it has been opened the timer is set back
to immediate polling.
bounce should do this also — there is little point in drawing when iconic unless
you are drawing a single compute-intensive image.
Detecting when the Program is
Iconic
microsystems
Revision A, of May 9, 1988
i
Index
A
action procedure for menu item, 229
alarm(3), 285
alert, 199
arrow, 201
beeping, 202
buttons, 201
components of, 201
controlling beeping, 208
creation, 202
described, 199
example program, 389
interface summary, 316
messages and simple buttons, 203
position of, 202
table of attributes, 316
table of functions, 318
text message, 201
types of buttons, 204
use with blocking pop-ups, 47
uses of, 201
using trigger events, 206
alert attributes, 316
ALERT_BUTTON, 316
ALERTJBUTTON_FONT, 316
ALERT_BUTTON_NO, 204, 316
ALERT_BUTTON_YES, 204, 316
ALERT_MES S AGE_, 203
ALERT_MESSAGE_FONT, 316
ALERT_ME S SAGE_STR I NGS, 316
ALERT_MESSAGE_STRINGS_ARRAY_PTR, 316
ALERT_NO_BEEP ING, 208, 316
ALERT__OP T I ONAL, 317
ALERT__P OS IT I ON, 317
ALERTJTRIGGER, 207, 317
alert functions, 318
alert_prompt (), 202, 318
possible status values, 202
ASCH events, 86
asynchronous signal notification, 293
ATTR__COL, 54, 160, 309
ATTR_COLS, 310
ATTR__LIST, 311
ATTR_ROW, 54, 160, 309
ATTR_ROWS, 310
attribute functions
attr create_list (),310
attribute lists
creating reusable lists, 310
default attributes, 311
maximum size, 29, 311
overview, 28
utilities, 309
attribute ordering, 55
for canvases, 69
in text subwindow, 132
B
base frame, 16
boundary manager, 19
button image constructor, 168
button panel item, 158, 167 thru 169
buttons with menus, 168
c
callback procs, 20
callback style of programming, 20
canvas, 61
attribute order, 69
automatic sizing, 69
backing pixrect, 66
canvas space vs. window space, 70, 98
color in canvases, 72
coordinate system, 65
default input mask, 70
definition of, 61
handling input, 70
interface summary, 319
model, 65
monochrome in multiple plane groups, 125
non-retained, 66
pixwin, 63, 65
repaint procedure, 66
repainting, 66
resize procedure, 67
retained, 66
scrolling, 64
table of attributes, 319
table of functions and macros, 320
tracking changes in size, 67
writing your own event procedure, 70
canvas attributes, 319
CANVAS__AUTO__CLEAR, 66, 319
CANVAS__AUTO_EXPAND, 69, 319
CANVAS AUTO_SHRINK, 69, 319
- 489 -
Index — Continued
canvas attributes, continued
CANVA S__FA S T_MON0, 319
CANVAS_F I XED_I MAGE, 67, 319
CANVAS__HE IGHT, 65, 319
CANVAS_MARGIN, 65, 319
CANVASJPIXWIN, 65, 103, 319
CANVAS_REPAINT_PROC, 66, 319
CANVAS_RESIZE_PROC, 319
CANVAS_RE TAI NED, 66, 319
CANVAS__WIDTH, 65, 69, 319
canvas functions and macros, 320
canvas_event (), 71, 98, 320
canvas_pixwin (), 63, 65, 103, 320
canvas_window_event (), 70, 320
CAP SMASH, 96, 97
character unit macros
ATTR_COL, 54, 160, 309
ATTR_COLS, 310
ATTR_ROW, 54, 160, 309
ATTR_ROWS, 310
child process control using the Notifier, 288
choice panel item, 158,170 thru 176
classes of windows, 16
client handle used by the Notifier, 287
clipping in a pixwin, 112
code examples, see example programs
color, 113
advanced colormap manipulation example program, 441
animation, 122, 447
background color of pixwin, 115
color during fullscreen access, 119
colormap, 113
colormap access, 118
colormap segment, 114
cursors and menus, 119
default colormap segment, 115
determining if display is color, 119
example programs, 441
fast color change, 114
foreground color of pixwin, 115
FRAME_BACKGROUND_COLOR, 115
FRAME_F OREGROUND_COLOR, 115
FRAME_INHERIT_COLORS, 115
grayscale compatibility, 120
hardware double-buffering, 122
in canvases, 72
introduction, 113
one colormap segment per window, 116
showcolor , 116
software double-buffering, 120,122
software double-buffering example program, 447
table of color functions, 360
using color, 119
compiling SunView programs, 27
confirmation
FRAME_N0_C0NF IRM, 382
control structure in Notifier-based programs, 21
converting existing programs to use the Notifier, 303
converting programs to SunView
attribute-value interface, 478
cursors, 480
equivalent SunWindows routines, 484
converting programs to SunView, continued
gfx subwindow-based, 485
gfx subwindow-based examples, 454
icons, 480
input events, 481
menus, 481
new objects, 479
non-window based programs, 477
panels, 482
prompts, 483
signals, 483
SunWindows-based, 477
typedefs, 478
windows, 482
write a prompt. .. read a reply , 216
CTRLMASK, 96, 97
cursor, 253
crosshair border gravity, 258
crosshair gap, 258
crosshair length, 258
crosshairs, 256
definition of, 253
fullscreen crosshairs, 258
hot spot, 257
interface summary, 321
rasterop, 257
setting position of mouse cursor, 91
table of attributes, 321
table of functions, 323
cursor attributes, 321
CURSOR_CROSSHAIR_BORDER_GRAVITY, 258, 321
CURSOR__CROSSHAIR_COLOR, 321
C UR S OR__CROS SH AI R_G AP , 258, 321
CURSOR__CROSSHAIR_LENGTH, 258
CURSOR_CROSSHAIR_OP, 321
CURSOR_CROSSHAIR__THICKNESS, 321
CURSOR_FULLSCREEN, 258, 321
CURSOR_HORIZ_HAIR_BORDER_GRAVITY, 321
CURSOR_HORIZ_HAIR_COLOR, 321
CURSOR_HORIZ_HAIR_GAP, 321
CURSOR_HORIZ_HAIR_OP, 321
CURSOR_HORIZ_HAIR_THICKNESS, 321
CURSOR_I MAGE, 256, 257, 321
CURSOR_OP, 257, 321
CURSOR_SHOW_CROSSHAIRS, 321
CURSOR_SHOW_CURSOR, 321
CURSOR__SHOW_HORI Z_HAIR, 321
C UR S OR_S HOW_VERT__H AIR, 321
CURSOR__VERT__HAIR__BORDER_GRAVITY, 322
CURSOR_VERT_HAIR_COLOR, 322
C URSOR__VERT_H AI R_GAP , 322
CUR S OR_VERT_H AI R_OP , 322
CURSOR_VERT_HAIR_THICKNESS , 322
CURSOR_XHOT, 257, 322
CURSOR_YHOT, 257, 322
cursor constants
CURSOR_TO_EDGE, 258
cursor functions, 323
cursor_copy (), 255, 323
cursor_create (), 255, 323
cursor_destroy (), 255, 323
cursor_get (), 255, 323
cursor_set (), 255, 323
- 490 -
Index — Continued
CURSOR_TO_EDGE, 258
cycle panel item, 174
D
data types, 324
caddr_t, 28
object handles, 28
opaque, 28
default colormap segment, 115
default system font, 41
DEFINE_ICON__FROM_IMAGE (), 40, 262
DE STROY_CHECKING, 300
DESTROY_CLEANUP, 300
DE STROY_PROCES S_DEATH, 300
destroying windows
FRAME_N0_CONFIRM, 382
destruction of objects, 300
disable Quit confirmation
FRAME_NO_CONFIRM, 41, 382
dispatching events
calling the Notifier explicitly, 303
calling the Notifier implicitly, 303
display
batching, 110
canvases and gfxsw’s in multiple plane groups, 125
determining if in color, 119
enable plane, 124
locking, 109
locking and batching interaction, 112
overlay plane, 124
plane group, 124
software double-buffering, 120
speed, 108
distribution of input in a window, 90
E
event
ASCD event codes, 86
canvas space vs. window space, 70, 98
definition of, 80
function key event codes, 88
keyboard focus event codes, 88
META event codes, 86
mouse button event codes, 86
mouse motion event codes, 86
panel space vs. window space, 193
reading events explicitly, 97
relationship to Notifier, 20
repaint and resize event codes, 87
shift key event codes, 89
timeout, 294
using an event with alerts, 206
window entry and window exit event codes, 87
event codes, 330, 82
BUT (),86
KBD_DONE, 88
KBD_REQUEST, 88
KBD_USE, 88
KEY_LEFT, 88
KEY_RIGHT, 88
KEYJTOP, 88
LOC DRAG, 70, 86
event codes, continued
LOC__MOVE, 86
LOC_RGNENTER, 87
LOC_RGNEX IT, 87
LOC_STILL, 86
LOC_TRAJECTORY, 86
LOC_WINENTER, 87
LOC_W INEXIT, 87
MS_LEFT, 86
MS_MIDDLE, 86
MS_RI GHT, 86
PANEL_EVENT_CANCEL, 190
PANEL_EVENT_DRAG_IN, 190
PANEL_EVENT_MOVE_IN, 190
SCROLL__REQUEST, 80
SHIFT_CAPSLOCK, 89
SHIFT_CTRL, 89
SHIFT_LEFT, 89
SHIFT_LOCK, 89
SHIFT_META, 89
SHIFT_RIGHT, 89
WIN_REPAINT, 70, 87
WIN_RESIZE, 70, 87, 299
WIN_STOP, 88
event descriptors, 333
WI N_ASC 11_E VENT S, 70, 90, 333
WIN_IN__TRANSI T_EVENTS, 90, 333
WIN_MOUSE_BUTTONS, 90, 333
WIN_NO_EVENTS, 90, 333
WIN_UP_ASCII_EVENTS, 90, 333
WI N_UP_EVENTS, 90, 333
event handling
at the Notifier level, 288
in canvases, 70
in panels, 189
event procedure
form of, 81
writing your own for a canvas, 70
writing your own for a panel item, 191
event state retrieval macros
event_action (), 96
event_ctrl_is__down (), 96
event_is_ascii (), 96
event_is__button (), 96
event_i s_down (), 96
event_is_key_lef t (), 96
event__is_key_right (), 96
event_is_key_top (), 96
event_is_meta 0,96
event_is_up (), 96
event_meta_is_down (), 96
event_shift_is_down (), 96
event_shiftmask (), 96
event_time (), 96
event_x (), 96
event_y (), 96
event state setting macros
event_set_down (), 97
event_set__id (), 97
event_set_shiftmask (), 97
event__set_time (), 97
event_set_up (), 97
event_set_x (), 97
491-
Index — Continued
event state setting macros, continued
event_set_y (), 97
event stream, 80
example programs, 389
animatecolor , 122,447
bounce , 454
color manipulation, 441
color edit, 118,441
colormap manipulation, 441
converting terminal-based programs, 216
creating menus, 416
detool , 430
discussion of image browser_1 program, 50
discussion of image browser2, 53
discussion of simple file manager, 44
filer , 44,389
fontjnenu , 416
gfx subwindow-based demos converted to SunView, 454
gfxsw_init to SunView, 454,461
image browser_1, 401
image browser_2, 406
list files in tty subwindow, 42
minimal SunView program, 37
notify_dispatch (), 216,454
notify__set__itimer_func (), 461
resize_demo, 52, 299,425
row/column space in a window, 406
show color, 116
simple file manager, 389
simple panel window, 39
spheres, 461
sub window layout, 401
tty subwindow escape sequences, 412
tty subwindow I/O, 412
tty jo, 412
typein, 437
F
f cntl(2), 286,290
file descriptor usage, 57
filer , 44
flow of control in Notifier-based programs, 21
font functions
pf_default (),41,106
pf_open (),41
frame
command line frame attributes, 386
definition of, 16
fitting around subwindows, 41
frame header, 18
layout of subwindows within a frame, 51,52, 299,425
menus, 18
modifying destruction using the Notifier, 299
modifying open/close using the Notifier, 297
table of attributes, 382
frame attributes, 382
FRAME_ARGC_PTR_ARGV, 40, 382
FRAME_ARGS, 55, 382
FRAME_BACKGROUND_COLOR, 115,382
FRAME_CLOSED, 382
FRAME_CLOSED_RECT, 382
FRAME_CMDLINE_HELP_PROC, 382
FRAME CURRENT RECT, 382
frame attributes, continued
FRAME_DEFAULT_DONE_PROC, 382
FRAME_DONE_PROC, 382
FRAME_EMBOLDEN_LABEL, 382
FRAME_FOREGROUND_COLOR, 115, 382
FRAME_ICON, 40,382
FRAME_INHERIT_COLORS, 115, 382
FRAME_LABEL, 40, 382
FRAME_NO_CONFIRM, 41, 382
FRAME_NTH_SUBFRAME, 383
FRAME_NTH_SUBWINDOW, 383
FRAME_NTH_WINDOW, 383
FRAME_OPEN_RECT, 383
FRAME_SHOW_LABEL, 40, 45, 383
FRAME_SUBWINDOWS_ADJUSTABLE, 383
free(3), 311
function keys, 88
G
generate procedure
for menu, 244
for menu item, 243
for pull-right, 246
generate procedure operation parameter values
MENU_DISPLAY, 242
MENU_DISPLAY_DONE, 242
MENU_NOTIFY, 242
MENU_NOTIFY_DONE, 242
getitimer(2), 285
gfx subwindow
pw_use_f ast_monochrome (), 125
converted demo programs, 454, 461
converting to SunView, 485
demo programs converted to SunView, 454
monochrome in multiple plane groups, 125
H
header files
overview, 27
<suntool/canvas.h>, 61
<suntool/icon .h>, 261
< suntool/menu .h>, 221
<suntool/panel.h>, 153
<suntool/scrollbar .h>, 165,267
<suntool/seln .h>, 279
<suntool/sunview.h>, 27
<suntool/textsw.h>, 129
<suntool/tty .h>, 211
<sunwindow/attr.h>, 311
<sunwindow/cms_mono.h>, 115
<sunwindow/pixwin.h>, 101
<sunwindow/rect.h>, 52
<sunwindow/win_cursor.h>, 253
<sunwindow/win_input.h>, 77
<sunwindow/window_hs. h>, 77, 101
i
icon, 261
definition of, 19
interactive editor for icon images, 262
interface summary, 328
Loading Icon Images At Run Time, 263
modifying the icon’s image, 263
-492-
Index — Continued
icon, continued
table of attributes, 328
table of functions and macros, 329
icon attributes, 328
ICON_FONT, 328
I CON_HE IGHT, 328
ICON__IMAGE, 328
I CON_I MAGE_RECT, 328
ICON_LABEL, 328
I CON_LABEL__RECT, 328
ICON_WIDTH, 328
icon functions and macros, 329
DEFINE_ICON_FROM_IMAGE (), 40, 262,329
icon__create (), 262, 329
icon_destroy (), 329
icon_get (), 329
icon_set () , 329
image browser _1 , 50
image browser _2, 53
images
in icons, 262
in menus, 227
mpr_static (), 227, 262
using images generated with iconedit, 227, 262
include files — see “header files”, 27
initiating event processing, 35
input, 77
ASCD events, 90, 333
designee, 92
environment, 79
event descriptors, 90
event macros, 96, 97
flow of control, 97
focus, 91
focus control, 91
grabbing all input, 92
in canvases, 70
interface summary, 330
keyboard focus, 88, 91
keyboard mask, 91
mask, 91 thru 95
mouse motion, 86
pick focus, 91
pick mask, 91
reading, 97
recipient, 92
refusing the keyboard focus, 88
releasing, 92
shift state, 97
state, 96
table of event codes, 82, 330
table of event descriptors, 333
table of input-related window attributes, 334
Virtual User Input Device ( VUID ), 80
input event codes
SCROLL_REQUEST, 83, 331
interposition, 287, 296 thru 302
interval timers, 294 thru 296
ioctl(2), 286
it_interval struct, 296
K
KBD__DONE, 88
KBD_REQUE ST, 88
KBD_USE, 88
KEY_LEFT, 88
KEY_RIGHT, 88
KEYJTOP, 88
keyboard focus, 88
L
layout of items within a panel, 160
layout of subwindows within a frame, 51
libraries used in SunView, 27
LOC_DRAG, 86
LOC_MOVE, 86
LOC_RGNENTER, 87
LOC_RGNEXIT, 87
LOC_STILL, 86
LOCJTRAJECTORY, 86
LOCJfINENTER, 87
LOC_WINEXIT, 87
locator, see mouse
locator motion event codes, 86
M
Menu, 327
menu
attributes to add pre-existing menu items, 235
basic usage, 224
callback procedures, 240
client data, 228
default selection, 249
destruction, 238
display stage of menu processing, 241
example program, 416
for panel items, 158
generate procedure, 242
inactive items, 231
initial selection, 249
interface summary, 335
notification stage of menu processing, 242
notify procedure, 228, 247
pull-right, 221
searching for a menu item, 239
shadow, 228
table of attributes, 335
table of functions, 341
table of menu item attributes, 339
user customizable attributes, 250
walking, 221
menu attributes, 335
MENU_ACT ION_IMAGE, 237, 335, 339
MENU_ACTI ON_ITEM, 237, 335, 339
MENU_ACTION_PROC, 339
MENU_APPEND_I TEM, 235, 335, 339
MENU_BOXED, 231, 250, 335, 339
MENU_CENTER, 335, 339
MENU_CLIENT_DATA, 228, 335, 339
MENU__COLUMN_MAJOR, 335
MENU_DEFAULT, 335
MENU DEFAULT_ITEM, 249, 335
-493-
Index — Continued
menu attributes, continued
MENU_DEFAULT_SELECT I ON, 249,250,335
MENU_DESCEND_F IRST, 239, 335
MENO_FEEDBACK, 234, 339
MENU_FIRST_EVENT, 335
MENU_FONT, 228,233, 250, 335,339
MENO_GEN_PROC, 242, 243, 244, 335, 339
MENU_GEN_PROC_IMAGE, 339
MENU_GEN_PROC_ITEM, 242, 339
MENU_GEN_PULLRIGHT, 246, 339
MENO_GEN_PULLRIGHT_IMAGE, 237, 246, 335, 339
MENU_GEN_PULLRIGHT_ITEM, 237, 246, 335, 339
MENO_IMAGE, 339
MENU_IMAGE_ITEM, 225, 229, 237, 336, 339
MENU_IMAGES, 227, 237, 336
MENU_INACTIVE, 231, 339
MENU_INITIAL_SELECTION, 249, 250, 336
MENU_INITIAL_SELECTION_EXPANDED, 250, 336
MENU_INITIAL_SELECTION_SELECTED, 250, 336
MENU_INSERT, 234, 235, 336
MENU_INSERT_I TEM, 235, 336
MENO_INVERT, 340
MENU_ITEM, 226,233, 237,336
MENU_JUMP_AFTER_NO_SELECTION, 250, 336
MENU_JUMP_AFTER_SELECT I ON, 250, 336
MENU_LAST_EVENT, 336
MENU_LEFT_MARGIN, 230, 250, 336, 340
MENU_MARG I N, 230, 231, 250, 336, 340
MENU_NCOLS, 231, 336
MENU_NI TEMS, 233, 336
MENU_NOT I FY_PROC, 337
MENU_NROWS, 231, 336
MENU_NTH_ITEM, 233, 337
MENU_PARENT, 337, 340
MENU_PULLRIGHT, 226,233, 340
MENU_PULLRIGHT_DELTA, 250, 337
MENU_PULLRIGHT_IMAGE, 237, 337, 340
MENU_PULLRIGHT_ITEM, 236,237,337, 340
MENU_RELEASE, 234, 238, 340
MENU_RELEASE_I MAGE, 340
MENU_REMOVE, 235, 337
MENU_REMOVE_ITEM, 235, 337
MENO_REPLACE, 235, 337
MENU_REPLACE_ITEM, 235,337
MENU_RIGHT_MARGIN, 230,250, 337,340
MENU_SELECTED, 337, 340
MENU_SELECTED_ITEM, 249, 337
MENU_SHADOW, 228,232,250, 337
MENU_STAY_UP, 337
MENU_STRING, 226,233,340
MENU_STRING_ITEM, 225, 229, 237, 337, 340
MENU_STRINGS, 237, 337
MENU_TITLE_IMAGE, 228, 338
MENU_TITLE_ITEM, 228, 338
MENUJTYPE, 338,340
MENU_VALID_RESULT, 338
MENU_VALUE, 225, 229, 340
menu callback procedures
generate procedures, 242
notify and action procedures, 247
menu data types
Menu, 327
Menu_generate, 242, 327
Menu item, 327
menu functions, 341
menu_create (), 224, 341
menu_create_item (), 234, 341
menu_destroy (), 238, 341
menu_destroy_with_proc (), 238, 341
menu_find (), 239, 341
menu_get (), 224, 341
menu_return_item (), 342
menu_return_value (), 342
menu_set (), 224, 341
menu_show (), 224, 229,240, 244, 341
menu_show_using_fd (), 342
menu item
action procedure, 229,247
generate procedure, 229
margins, 230
table of attributes, 339
value of, 229
menu package, 221 thru 251
menu processing
display stage, 240
notification stage, 240
MENU_DISPLAY, 242
MENU_DISPLAY_DONE, 242
Menu_generate, 242, 327
Menu_item, 327
MENU_NOTIFY, 242
MENU_NOTIFY_DONE, 242
menu_prompt (), 483
message panel item, 158,167
META events, 86
META_SHIFT_MASK, 96, 97
mouse
event codes for mouse buttons, 86
setting position of mouse cursor, 91
tracking, 86
mpr_static (), 227, 262
MS_LEFT, 86
MS_MIDDLE, 86
MS_RIGHT, 86
multiple views in text subwindows, 147
N
namespaces reserved by Sun View, 30
Notifier
asynchronous signal notification, 293
base event handler, 296
child process control events, 288
client handle, 287
converting existing programs to use the Notifier, 303
debugging, 306
discarding the default action, 299
error handling, 305
event handler function, 287
flow of control in Notifier-based programs, 21
interposing on frame open/close, 297
interposing on resize events, 299, 425
interposition, 287
overview, 20, 287
pipes, 290
polling, 295
-494-
Index — Continued
Notifier, continued
prohibited signals, 286
prohibited system calls, 285
registering an event handler, 288
restrictions imposed on clients, 285
signal events, 291
table of functions, 343
when to use, 285
Notifier functions, 343
notify__default__wait3 (), 288,343
notify_dispatch (), 303,343
not ify_do_di spat ch (), 216, 304, 343
not if y_dump (), 306
notify_interpose_destroy_func (), 299, 343
notify_interpose_event_func (), 297, 343
notify_interpose_wait3_func (), 215
notify_itimer_value (), 285, 296, 343
notify_next_destroy_func (), 343
notify__next_event_func (), 297, 344
not ify_no__di spat ch (), 304, 344
notify_perror (), 305, 344
notify_set_destroy_func (), 286, 344
notify_set_exception_func (), 286, 344
notify_set__input_func (), 286, 290, 292, 344
notify__set_itimer_func (), 285, 294, 295, 296,344
notify__set_output__func (), 286, 292, 345
notify_set_signal_func (), 88,287, 291, 345
notify_set__wait3_func (), 286, 288, 345
not if y_start (), 345
notify__stop (), 304, 345
notify__veto_destroy (), 300, 345
notify procedure
for menu, 228
for panel button items, 167
for panel choice items, 172
for panel slider items, 184
for panel text items, 180
for panel toggle items, 176
notify procs, 20
NOTIFYJDONE, 288, 289, 290, 295, 300, 302
notify__errno, 305
Notify_error, 305
NOT I FY_ERROR__ABORT, 306
NOTIFY_FUNC_NULL, 291, 305
N0TIFY_IGN0RED, 288, 289, 293
NOTIFY_OK, 305
NOTIFY_POLLING_ITIMER, 295
o
object
definition of, 9
destruction of, 300
handle, 28
non-window visual objects, 11
window objects, 11
opening a font, 41
p
painting panels and panel items, 185
panel, 153,327
action functions, 190
attributes, 346
panel, continued
attributes applying to all item types, 160
caret, 179
caret item, 179
caret manipulation, 180
creation, 159
data types, 327
default event-to-action mapping, 189
definition of, 158
event handling mechanism, 189
interface summary, 346
item label, 158
item menu, 158
iterating over all items in a panel, 188
modifying attributes, 162
painting, 185
panel space vs. window space, 193
panel-wide item attributes, 163
positioning items within a panel, 160
retrieving attributes, 163
simple panel window example, 39
table of attributes, 346
table of functions and macros, 353
table of generic panel item attributes, 347
using scrollbars with, 165
panel attribute settings
PANEL_ALL, 170,176, 180, 184
PANEL_CLEAR, 185
PANEL_CURRENT, 170
PANEL_DONE, 184
PANEL_HORI ZONTAL, 162,178
P ANEL_I NVERTE D, 172
PANEL_MARKED, 172
PANEL_NO_CLEAR, 185
PANEL_NON_PRINTABLE, 180
PANEL_NONE, 170, 172, 176,180, 185
PANEL_SPECIFIED, 180
PANEL_VERT I CAL, 162, 170,178
panel attributes, 346
PANEL_ACCEPT_KEYSTROKE, 189, 190, 346, 347
PANEL_BACKGROUND_PROC, 189,190, 346
PANEL_BLINK_CARET, 164, 346
PANEL_BUTTON, 160
PANEL_CARET_I TEM, 162,179,346
PANEL_CHOICE, 160
PANEL_CHOICE_FONTS, 349
PANEL_CHOICE_IMAGE, 164, 349
PANEL_CHOICE_IMAGES, 170, 349
PANEL_CHOICE_STRING, 349
PANEL_CHOICE_STRINGS, 170, 349
PANEL_CHO I CE_X, 349
PANEL_CHOICE_XS, 170, 349
PANEL_CHO I CE_Y, 349
PANEL_CHO I CE_YS, 349
PANEL_CHOICE_YS ,, 170
PANEL_CHOICES_BOLD, 349
PANEL_CLIENT_DATA, 188, 347
PANEL_CYCLE, 160
PANEL_DISPLAY_LEVEL, 170, 176, 349
PANEL_EVENT_PROC, 189,191, 346, 347
PANEL_FEEDBACK, 172, 349
PANEL_FIRST_ITEM, 188, 346
PANEL_ITEM_RECT, 347
PANEL ITEM_X, 160, 347
-495-
Index — Continued
panel attributes, continued
PANEL_ITEM_X_GAP, 161, 346
PANEL_ITEM_Y, 160, 347
PANEL_ITEM_Y_GAP, 161, 346
PANEL_LABEL_BOLD, 163, 346, 347
PANEL_LABEL_FONT, 347
PANE L_L ABE L_ I MAGE, 167, 347
PANEL_LABEL_STRING, 167, 347
PANEL_LABEL_X, 162, 347
PANEL_LABEL__Y, 162, 347
PANEL_LAYOUT, 162, 163, 170, 178, 346, 347, 349
P ANEL_MARK__I MAGE, 349
PANEL_MARK_I MAGES, 170, 350
PANEL_MARK_X, 350
PANEL_MARK__XS, 170, 350
PANEL_MARK_Y, 350
PANEL_MARK_YS, 170, 350
PANEL_MASK_CHAR, 352
PANEL_MAX_VALUE, 184, 185, 351
PANE L_MEN U_CHO I CE_F ONT S, 347
PANEL_MENU__CHOICE_IMAGES, 347
PANEL_MENU_CHOICE_STRINGS, 183, 347
PANEL_MENU_CHOI CE_VALUES, 183, 348
PANEL_MENU_MARK_I MAGE, 178, 350
PANEL_MENU_NOMARK_I MAGE, 178, 350
PANEL__MENU_TITLE_FONT, 348
PANEL_MENU__T ITLE__IMAGE, 348
PANEL_MENU_TITLE_STRING, 348
P ANEL_ME S SAGE, 160
PANEL_MIN_VALUE, 184, 185, 351
PANEL_NEXT_ITEM, 188, 348
PANEL_NOMARK_IMAGE, 350
PANEL_NOMARK_IMAGES, 170, 350
PANEL_NOTIFY_LEVEL, 180, 184, 351, 352
PANEL_NOTIFY_PROC, 167,172, 180, 348
PANEL_NOTIFY_STRING, 180, 352
PANEL_PAI NT, 163, 185, 348
PANEL_PARENT_PANEL, 348
PANEL_SHOW_I TEM, 164, 179, 348
PANEL_SHOW_MENU, 163, 346, 348
PANEL_SHOW_MENU_MARK, 172, 350
PANEL_SHOW_RANGE, 184, 351
PANEL_SHOW_VALUE, 184, 351
PANEL_SLIDER_WIDTH, 184, 351
PANELJTEXT, 160
PANEL_TOGGLE, 160
PANEL_TOGGLE_VALUE, 350
PANEL_VALUE, 162, 163, 185, 350, 351, 352
PANEL__VALUE_DI SPLAY_LENGTH, 178, 352
PANEL_VALUE_FONT, 351, 352
PANEL_VALUE_STORED_LENGTH, 179, 352
PANEL_VALUE_X, 162, 348
PANEL_VALUE_Y, 162, 348
panel data types
Panel, 327
Panel_attribute, 327
Panel_item, 327
Panel_setting, 327
panel functions and macros, 353
panel_accept_key (), 191, 353
panel_accept_menu (), 191,353
panel_accept_preview (), 191,353
panel_advance_caret (), 180, 353
panel_backup__caret (), 180, 353
panel functions and macros, continued
panel_begin_preview (), 191,353
panel_button_image (), 168, 353
panel_cancel__preview (), 191, 353
panel_create_item (), 41, 160, 353
panel_default_handle_event (), 190, 354
panel_destroy_item (), 164, 354
panel__each_item (), 354
panel_event (), 194,354
panel_get (), 163, 354
panel_get_value (), 164
panel_jpaint (), 185, 354
panel_set (), 162, 354
panel_set_value (), 162
panel_text_notify (), 181, 354
panel_update_preview (), 191, 355
panel__update_scrolling_size (), 165, 355
panel_window_event (), 194, 355
panel item
accepting selection, 189
basic item types, 158
button item, 158, 167 thru 169
choice item, 158, 170 thru 176
choice item “creep”, 161
creation, 160
cycle item description, 174
default positioning, 161
destroying, 164
explicit positioning, 160
item types for creation routine, 160
layout of components, 162
message item, 158,167
modifying attributes, 162
painting, 185
positioning, 160
previewing selection, 189
retrieving attributes, 163
slider item, 159, 184 thru 185
table of choice and toggle item attributes, 349
table of slider item attributes, 351
table of text item attributes, 352
text item, 159,178 thru 183
toggle item, 159, 176 thru 178
Panel_attribute, 327
PANEL_EVENT__CANCEL, 190
P ANEL_EVENT_DRAG__I N, 190
PANEL_EVENT_MOVE_IN, 190
PANEL_INSERT, 181
Panel_item, 327
PANEL_NEXT, 181
PANEL_NONE, 181
PANEL_PREVIOUS, 181
Panel_setting, 327
performance hints — locking and batching, 108
perror(3), 305
pipes, 290
pixels, 103
pixrect, 103
pixwin, 101
background color, 115
batching, 109,110
bitplane control, 120
-496-
Index — Continued
pixwin, continued
cgf our frame buffer, 124
changing region size, 112
clipping in a pixwin, 112
clipping with regions, 112
colormap, 118
colormap manipulation, 113
colormap name, 117
destruction, 113
determining region size, 112
foreground color, 115
interface summary, 356
inverting colors, 119
locking, 108, 109
locking and batching interaction, 112
performance hints, 109, 110
plane groups, 124
positioning, 52
rasterop function, 104
regions, 112
rendering speed, 108
retained regions, 112
table of color manipulation functions, 360
table of drawing functions, 356
what is a pixwin?, 103
write routines, 104
writing text, 106
pixwin functions and macros, 356
pw_use__fast_monochrome (), 125
pw_batch(), 111
pw_batch_off (), 111,356
pw_batch_on (), 111, 356
pw_batchrop (), 106, 356
pw_blackonwhite (), 119,360
pw_char (), 105,356
pw_close (), 113, 356
pw_copy (), 108,356
pw_cy c l ec °l° rma p (), 118, 360
pw_dbl_access (), 123, 360
pw_dbl_flip (), 123,360
pw_dbl__get (), 124, 360
pw_dbl_release (), 123, 360
pw_dbl_set (), 124, 360
pw_get (), 108, 356
pw_get_region_rect (), 112, 356
pw_getattributes (), 120, 360
pw_getcmsname (), 117, 360
pw_getcolormap (), 118, 360
pw_getdefaulterns (), 361
pw_line (), 107,357
pw__lock (), 109,357
PW _ 0P _ C0UNT ’ 111
pw_pf sysclose (), 106, 357
pw_pf sysopen (), 106,357
pw_polygon__2 (), 107,357
pw_polyline (), 107, 357
pw_polypoint (), 105, 357
pw_put (), 104, 357
pw_putattributes (), 120, 361
pw_putcolormap (), 118, 121, 361
pw_read (), 108,358
pw_region (), 112, 358
pw_replrop (), 105, 358
pw_reset (), 110, 358
pixwin functions and macros, continued
pw_reversevideo (), 119, 361
pw_rop (), 104,358
pw_set_region__rect (), 112, 358
pw_setcmsname (), 117, 361
pw_show (), 111, 358
pw_stencil (), 106, 358
pw_text (), 106, 359
pw_traprop (), 107, 359
pw_ttext (), 106, 359
pw_unlock (), 109, 359
pw_vector (), 105, 359
pw__whiteonblack (), 119, 361
pw_write (), 104, 359
pw__writ©background (), 104, 359
text routines, 105
polling, 295
pop-up windows, 16,44 thru 49
blocking, 47
example program, 389
non-blocking, 46
restrictions, 49
porting programs to SunView, 303
SunWindows-based, 477, see converting programs to Sun-
View
programmatic scrolling, 275
pty (pseudo-tty), 57
pw_batch, 111, 356
R
reading events, 97
Rect struct, 52
refusing the keyboard input focus, 88
regions of a pixwin, 112
registering an event handler with the Notifier, 288
releasing the event lock, 97
rendering speed, 108
reserved namespaces, 30
restrictions on use of UNIX facilities by SunView applications, 285
row/column space in a window, 53
example program, 406
s
sample programs, see example programs
Scroll_motion, 327
scrollbar, 267, 327
basic usage, 272
model, 269
programmatic scrolling, 275
SCROLLBAR default symbol, 272
table of attributes, 362
table of functions, 365
thumbing, 271
use with canvases, 64
use with panels, 165
user interface, 271
scrollbar attributes, 362
SCROLL_ABSOLUTE_CURSOR, 362
SCROLL_ACTIVE_CURSOR, 362
SCROLL_ADVANCED_MODE, 362
SCROLL_BACKWARD_CURSOR, 362
SCROLL BAR COLOR, 362
-497-
Index — Continued
scrollbar attributes, continued
SCROLL_BAR_DISPLAY_LEVEL, 362
SCROLL_BORDER, 362
SCROLL_BUBBLE_COLOR, 362
SCROLL__BUBBLE__DI SPLAY_LEVEL, 362
SCROLL_BUBBLE_MARGIN, 362
SCROLLED I RECTI ON, 273, 362
SCROLL__END_P 01 NT__AREA, 362
SCROLL_FORWARD_CURSOR, 362
SCROLL_GAP, 362
SCROLL_HEIGHT, 272, 363
SCROLL__LAST_VIEW_START, 275, 363
SCROLL_LEFT, 363
SCROLL_LINE_HEIGHT, 363
SCROLL_MARGIN, 363
SCROLL_MARK, 363
SCROLL_NORMALIZE, 363
SCROLL_NOTIFY_CLIENT, 363
SCROLLJDB JECT, 363
SCROLL_OB JECT_LENGTH, 269, 363
SCROLL_PAGE_BUTTON_LENGTH, 363
SCROLL_PAGE_BUTTONS, 363
SCROLL_P AI NT_BUTT ON S_P ROC, 363
SCROLL_PIXWIN, 363
SCROLL_PLACEMENT, 272, 363
SCROLL_RECT, 272, 363
SCROLL_REPEAT_T I ME, 364
SCROLL_REQUEST_MOTION, 364
SCROLL_REQUEST_OFFSET, 364
SCROLL_THICKNESS, 272, 273, 364
SCROLL_TO_GRID, 364
SCROLL_TOP, 364
SCROLL_VIEW_LENGTH, 269, 364
SCROLL_VIEW__ST ART, 269, 275, 364
SCROLL_WI DTH, 272, 364
scrollbar data types
Scroll_motion, 327
Scrollbar, 327
Scrollbar__attribute, 327
Scrollbar_attribute_value, 327
Scrollbar_setting, 327
scrollbar functions, 365
scrollbar_clear_bubble(), 365
scrollbar_create (), 165, 272, 365
scrollbar_destroy (), 272
scrollbar_get (), 272
scrollbar_jpaint (), 365
scrollbar_j>aint_bubble (), 365
scrollbar_j?aint_clear (), 365
scrollbar_scroll_to (), 275, 365
scrollbar__set (), 272, 365
Scrollbar_attribute, 327
Scrollbar_attribute_value, 327
Scrollbar_setting, 327
selection of panel items
buttons, 167
choices, 172
sliders, 184
text, 179
toggles, 176
Selection Service, 279
setting position of mouse cursor, 91
Setting the contents of a Text Subwindow
Setting the contents of a Text Subwindow, continued
Setting contents, 140
SHIFT_CAPSLOCK, 89
SHIFT_CTRL, 89
SHIFT__LEFT, 89
SHIFT_LOCK, 89
SHIFT_META, 89
SHIFT_RIGHT, 89
SHIFTMASK, 96, 97
show color, 116
SIGALRM, 286
sigblock(2), 293
SIGCHLD, 286
SIGCONT, 285
SIGIO, 286
signal(3), 285,291
Notifier-compatible version, 291
signals — use with Notifier, 291
SIGPIPE, 292
SIGTERM, 286
SIGURG, 88, 286
sigvec(2), 285
SIGVTALRM, 286
slider panel item, 159, 184 thru 185
stop key, 88
subframe, 16
subwindow layout
discussion of image browser_1 program, 50
example program, 401
subwindows, 16
changing layout dynamically, 52
definition of, 19
specifying layout, 51, 52
specifying size, 50
<suntool/canvas.h>, 61
<suntool/icon. h>, 261
< sunt ool/menu .h>, 221
<suntool/panel,h>, 153
<suntool/scrollbar .h>, 165,267
<suntool/seln.h>, 279
<suntool/sunview.h>, 27
<suntool/textsw.h>, 129
<suntool/tty.h>, 211
Sun View
changes in SunOS releases, 4
code no longer supported, 5
converting programs from SunWindows, 477
data types, 324
file descriptor limits, 57
frame header, 18
graphics standards in windows, 3
history, 4
interface outline, 27
interface summary, 315
libraries, 27
model, 9
objects, 9
overview, 3
plane groups, 126
porting programs to, 303
498-
Index — Continued.
SunView, continued
reserved namespaces, 30
restrictions on use of UNIX facilities by applications, 285
source code of programs, 389
standard functions for objects, 29
summary of object types, 11
<sunwindow/cms_mono .h>, 115
<sunwindow/rect.h>, 52
<sunwindow/win_cursor. h>, 253
SunWindows
converting programs to SunView, 477
equivalent code in SunView, Table C-l
system(3), 286
system calls not to be used under SunView, 285
T
terminal emulator subwindow — see “tty sub window’ ’, 211
text notification procedure
default, 181
possible return values, 181
text panel item, 159, 178 thru 183
text sub window, 129
as a sequence of characters, 132
attribute ordering, 132
checking its status, 133
concepts, 132
creation, 132
discarding edits, 139
edit log, 138
editing contents of, 136
and the file system, 138
finding text, 144
getting a text selection, 132
insertion point, 132,135,136,137
interface summary, 366
manipulating the backing store, 136
marking text, 145
matching a span of characters, 144
matching a specific pattern, 144
multiple views, 147
notification, 148
overflow of edit log, 138
positioning the caret, 135
positioning the text, 141
reading from, 135
saving edits, 139
setting selection, 147
storing edits, 139
table of attributes, 366
table of functions, 372
table of Text sw_act ion attributes, 149, 370
table of Textsw_status values, 134, 371
writing to, 134
text subwindow attributes, 366
TEXTSW__AD JUST_IS_PENDING__DELETE, 366
TEXTSW_AGAIN_RECORD ING, 366
TEXTSW_AUTO_INDENT, 366
TEXTSW__AUTO_SCROLL_BY, 366
TEXTSW__BLINK_CARE T, 366
TEXTSW_BROWSING, 366
TEXTSW_CHECKPOINT_FREQUENCY, 366
TEXTSW__CL IENT_DAT A, 366
TEXTSW CONFIRM OVERWRITE, 366
text subwindow attributes, continued
TEXTSW_CONTENTS, 135, 139, 366
TEXTSW__CONTROL_CHARS_USE_FONT, 366
TEXTSW_D I SABLE_CD, 366
TEXTSW_D I SABLE_LOAD, 367
TEXTSWJEDIT__COUNT, 367
TEXTSW_FILE, 46, 133, 367
TEXTSW_FILE_CONTENTS, 367
TEXTSW_FIRST, 133, 142, 367
TEXTSW_FIRST_LINE, 142, 367
TEXTSW_H I STORY__LIMIT, 367
TEXTSW_I GNORE_LIMI T, 367
TEXTSW_I NSERT__FROM_F I LE, 367
TEXTSW__INSERT_MAKES__VISIBLE, 367
TEXTSW_INSERTION_POINT, 135, 367
TEXTSW_LEFT_MARGIN, 367
TEXTSW_LENGTH, 132, 367
TEXTSW__L INE_BREAK_ACT I ON, 367
TEXTSW_LOWER_CONTEXT, 367
TEXTSW_MARK_DEFAULTS, 145
TEXTSW_MARK_MOVE_AT_INSERT, 145
TEXTSW_MEMORY_MAXIMUM, 138, 368
TEXTSW_MENU, 368
TEXTSW_MOD IFI ED, 133, 368
TEXTSW_MULTI_CLICK_SPACE, 368
TEXTSW_MULTI_CLI CK_TIMEOUT, 368
TEXTSW_NOTIFY_PROC, 148, 368
TEXTSW_READ_ONLY, 368
TEXTSW_SCROLLBAR, 368
TEXTSW_STATUS, 132, 133, 368
TEXTSW_STORE_CHANGES_FI LE, 368
TEXTSW_STORE_SELF_IS_SAVE, 368
TEXTSW_UPDATE_SCROLLBAR, 369
TEXTSW_UPPER_CONTEXT, 369
text subwindow constants
TEXTSW_I NFINITY, 135, 136, 137
TEXTSW_UNIT_IS_CHAR, 136
TEXTSW_UNIT_IS_LINE, 136
text subwindow data types
Textsw, 327
Textsw_index, 132, 327
Textsw_status, 133,327
text subwindow functions, 372
textsw_add_mark (), 145, 372
textsw__append_file_name (), 138, 372
textsw__delete (), 136, 372
textsw__edit (), 136, 372
textsw_erase (), 136, 372
textsw_f ile_lines_visible (), 143, 372
textsw_f indjbytes (), 144, 372
textsw_f ind__mark (), 146,373
textsw_first (), 147, 373
textsw_index_for_f ile__line (), 142,373
textsw_insert (), 134, 373
textsw_match_bytes (), 144, 373
textsw__next (), 147,373
textsw_normalize_view (), 143, 373
textsw_j?ossibly_normalize (), 143, 373
textsw_remove_rnark (), 146, 374
textsw_replace_bytes (), 137, 374
textsw__reset (), 139, 150, 374
textsw_save (), 139,150,374
textsw_screen_line__count (), 143,374
textsw scroll_lines (), 142,374
-499-
Index — Continued
text subwindow functions, continued
text sw_set_selection (), 147, 374
textsw_store (), 150
textsw_store_f ile (), 139,375
Textsw, 327
Text sw_act ion, 148
Text sw__action attributes, 370, 149
TEXTSW_ACTION_CAPS_LOCK, 149, 370
TEXT SW_ACT I ON_CHANGED_D I RECTORY, 149, 370
TEXTSW_ACTION_EDITED_FILE, 149, 370
TEXT SW_ACTION_FILE__I S_READONLY, 149, 370
TEXT SW_ACT I ON_LOADE D_F I LE, 149, 370
TEXT SW_ACTION_EDITED_FILE, 150
TEXT SW_ACTION_LOADED_FILE, 150
TEXTSW_ACTION_TOOL_CLOSE, 149, 370
TEXTSW_ACTION_TOOL_DESTROY, 149, 370
TEXT SW_ACT I ON_TOOL_MGR, 149, 370
TEXTSW_ACTION_TOOL_QUI T, 149, 370
TEXT SW_ACT I ON_US I NG_MEMORY, 149, 370
Text sw__index, 132, 327
TEXT S W_I NFINIT Y, 135, 136, 137
Textsw_status, 133, 327
Textsw_status values, 371, 134
TEXT SW_STATUS_BAD_ATTR, 134, 371
TEXTSW_STATUS__BAD_ATTR_VALUE, 134, 371
TEXT SW_STATUS_CANNOT_ALLOCATE, 134, 371
TEXT SW_STATUS_CANNOT_I NSERT_FROM_F ILE,:
371
TEXT SW_STATUS_CANNOT__OPEN__I NP UT, 134, 371
TEXTSW_STATUS_OKAY, 134, 371
TEXT SW_STATUS_OTHER_ERROR, 134, 371
TEXTSW__STATUS_OUT_OF_MEMORY, 134, 371
TEXT SW_UN I T_I S_CHAR, 136
TEXT S W__UN I T__I S_L INE , 136
timeout events, 294
toggle panel item, 159, 176 thru 178
translating events from canvas space to window space, 70, 98
translating events from panel space to window space, 193
tty subwindow
creating, 213
differences with Sun console, 214
example program, 412
example program to list files, 42
file descriptor, 215
input/output to tty subwindow, 213
interface summary, 376
monitoring, 215
overview, 211
reading and writing, 215
special escape sequences, 215
standard escape sequences, 214
table of functions, 376
table of special escape sequences, 377
tty subwindow attributes
TTY__ARGV, 213, 215, 216, 376
TTY_CONSOLE, 376
TTY_PAGE_MODE, 376
TTY_QUI T_ON_CH I LD_DEATH, 376
tty subwindow functions, 376
example program, 412
ttysw_input (), 42, 213, 376
ttysw_output (), 214, 376
u
UNIX system calls and SunView
alarm(3), 285
f cntl(2), 286, 290
f ree(3), 311
getitimer(2), 285
I/O in a tty subwindow, 215
ioctl(2), 286
perror(3), 305
sigblock(2), 293
signal(3), 285, 291
sigvec(2), 285
system calls not to be used, 285
wait(2), 286
wait3(2), 285, 288
v
views in text subwindows, 147
Virtual User Input Device ( VUID ), 80
w
wait(2), 286
wait3(2), 285, 288
WIN_ASC I I_EVENTS, 90, 333
WIN_EXTEND_TO_EDGE, 50, 51
WIN_IN_TRANSIT_EVENTS, 90, 333
WIN_LEFT_KEYS, 90, 333
WIN_MOUSE_BUTTONS, 90, 333
WIN_NO_EVENTS, 90, 333
WI N_REPAI NT, 87
WIN_RESIZE, 87
WIN_RIGHT_KEYS, 90, 333
WIN_STOP, 88
WIN_TOP_KEYS, 90, 333
WIN_UP_ASCII_EVENTS, 90, 333
WIN_UP_EVENTS, 90, 333
window, 33
classes of windows, 16
creation, 35
destruction, 36
initiating event processing, 35
interface summary, 379
limit to number of windows, 57
simplest SunView program, 37
table of attributes, 379
table of functions and macros, 384
table of input-related window attributes, 334
window attributes, 379
WIN_BELOW, 379
WIN_BOTTOM_MARGIN, 53, 379
WIN_CLIENT_DATA, 379
WIN_COLUMN_GAP, 53, 379
WIN_COLUMN_WI DTH, 53, 379
WIN_COLUMNS, 50, 159, 379
WI N_CONS UME_KBD_EVENT, 70, 379
WIN_CONSUME_KBD_EVENTS, 379
WIN_CONSUME_PICK_EVENT, 379
WIN_CONSUME_PICK_EVENTS, 379
WIN_CURSOR, 255, 256, 379
WIN_DEVICE_NAME, 379
WIN_DEVI CE_NUMBER, 379
WIN ERROR_MSG, 40, 379
-500-
Index — Continued
window attributes, continued
WIN_EVENT_PROC, 70, 81, 379
WIN_EVENT_STATE, 96, 379
WIN_FD, 379
WIN_FIT_HEIGHT, 41, 379
WIN_FIT_WIDTH, 41, 380
WIN_FONT, 41,160, 309, 380
WIN_GRAB_ALL_INPUT, 92, 380
WIN_HEIGHT, 159, 380
WIN_HORIZONTAL_SCROLLBAR, 165, 267, 380
WIN_IGNORE_KBD_EVENT, 380
WIN_IGNORE_KBD_EVENTS, 380
WIN_IGNORE_PICK_EVENT, 380
WIN_IGNORE_PICK_EVENTS, 380
WI N_INPOT_DESIGNEE, 92, 380
WIN_KBD_FOCUS, 380
WIN_KBD_INPOT_MASK, 380
WIN_KEYBOARD_F OCUS, 91
WIN_LEFT_MARGIN, 53, 380
WIN_MENU, 380
WIN_MOUSE_XY, 91, 380
WIN_NAME, 380
WIN_OWNER, 380
WIN_PERCENT_HEIGHT, 380
WI N_PERCENT_WI DTH, 381
WIN_PICK_INPUT_MASK, 381
WIN_PIXWIN, 65, 103, 381
WIN_RECT, 52, 381
WIN_RIGHT_MARGIN, 53,381
WIN_RIGHT_OF, 381
WIN_ROW_GAP, 53,381
WI N_ROW_HE I GHT, 53, 381
WIN_ROWS, 50,159, 381
WIN_SCREEN_RECT, 381
WIN_SHOW, 46, 381
WIN_TOP_MARGIN, 53, 381
WIN_TYPE, 381
WIN_VERTICAL_SCROLLBAR, 165, 267,381
WIN_WIDTH, 159,381
WIN_X, 52, 381
WIN_Y, 52, 381
window classes
base frame, 16
frame, 16
pop-up, 16
subframe, 16
subwindow, 16
window functions and macros, 384
window_bell (), 384
window_create (), 35, 63, 297,384
window_default_event_proc (), 81, 384
window_destroy (), 36,384
window_done (), 36, 384
window_fit (),384
window_fit_height (), 41,
window_f it_width (), 41, 384
window_get (), 35, 384
window_loop (), 48, 385
window_main_loop (), 35, 303, 385
window_read_event (), 71, 97, 193, 385
window_refuse_kbd_focus (), 88, 385
window_release_event_lock (), 97, 385
window_return (), 48, 385
window set (), 35,162,385
-501-
Notes
Notes
Notes
Notes
Notes
Notes
Notes